From 4e0b28f9c7d9bce6e762daeb9042d2b367c05e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 22 Dec 2025 08:07:27 +0100 Subject: [PATCH 01/48] feature/Add webui_obp_portal_url --- obp-api/src/main/resources/props/sample.props.template | 8 ++++++++ obp-api/src/main/scala/code/snippet/WebUI.scala | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index f9416680e..dc558759a 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -624,6 +624,14 @@ webui_agree_terms_url = #webui_post_consumer_registration_more_info_text = Please tell us more your Application and / or Startup using this link. #webui_post_consumer_registration_submit_button_value=Register consumer +# OBP Portal URL - base URL for the OBP Portal service +webui_obp_portal_url = http://localhost:5174 + +# External Consumer Registration URL - used to redirect "Get API Key" links to an external service +# If not set, defaults to webui_obp_portal_url + "/consumer-registration" +# Set this to redirect to a custom URL for consumer registration +webui_external_consumer_registration_url = http://localhost:5174/consumer-registration + ## Display For Banks section webui_display_for_banks_section = true diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index 63214fa92..d732bbec2 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -312,11 +312,11 @@ class WebUI extends MdcLoggable{ // External Consumer Registration Link // This replaces the internal Lift-based consumer registration functionality // with a link to an external consumer registration service. - // Uses webui_api_explorer_url + /consumers/register as default. + // Uses OBP-Portal (webui_obp_portal_url) for consumer registration by default. // Configure webui_external_consumer_registration_url to override with a custom URL. def externalConsumerRegistrationLink: CssSel = { - val apiExplorerUrl = getWebUiPropsValue("webui_api_explorer_url", "http://localhost:5174") - val defaultConsumerRegisterUrl = s"$apiExplorerUrl/consumers/register" + val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") + val defaultConsumerRegisterUrl = s"$portalUrl/consumer-registration" val externalUrl = getWebUiPropsValue("webui_external_consumer_registration_url", defaultConsumerRegisterUrl) ".get-api-key-link a [href]" #> scala.xml.Unparsed(externalUrl) & ".get-api-key-link a [target]" #> "_blank" & From 12fab148208b3af5952f6efeadd66095ef869d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 22 Dec 2025 08:45:36 +0100 Subject: [PATCH 02/48] feature/Reduce warning in tests --- obp-api/src/main/scala/code/api/util/AfterApiAuth.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala b/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala index 13eae4fc4..00ef0fa50 100644 --- a/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala +++ b/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala @@ -32,11 +32,12 @@ object AfterApiAuth extends MdcLoggable{ */ def innerLoginUserInitAction(authUser: Box[AuthUser]) = { authUser.map { u => // Init actions - logger.info("AfterApiAuth.innerLoginUserInitAction started successfully") + logger.debug("AfterApiAuth.innerLoginUserInitAction started successfully") sofitInitAction(u) } match { - case Full(_) => logger.warn("AfterApiAuth.innerLoginUserInitAction completed successfully") - case userInitActionFailure => logger.warn("AfterApiAuth.innerLoginUserInitAction: " + userInitActionFailure) + case Full(_) => logger.debug("AfterApiAuth.innerLoginUserInitAction completed successfully") + case Empty => // Init actions are not started at all + case userInitActionFailure => logger.error("AfterApiAuth.innerLoginUserInitAction: " + userInitActionFailure) } } /** From 233af77b753ededc3668f395a62c2446c589bb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Mon, 22 Dec 2025 14:46:09 +0100 Subject: [PATCH 03/48] feature/Remove Sign Up flow from legacy portal --- .../resources/props/sample.props.template | 26 ++- .../main/scala/code/api/util/Glossary.scala | 6 +- .../code/model/dataAccess/AuthUser.scala | 193 +----------------- .../src/main/scala/code/snippet/Login.scala | 7 +- .../code/snippet/OAuthAuthorisation.scala | 9 +- .../src/main/scala/code/snippet/WebUI.scala | 17 +- obp-api/src/main/webapp/index-en.html | 2 +- obp-api/src/main/webapp/index.html | 2 +- obp-api/src/main/webapp/oauth/authorize.html | 2 +- .../main/webapp/templates-hidden/_login.html | 2 +- .../webapp/templates-hidden/default-en.html | 6 +- .../templates-hidden/default-footer.html | 6 +- .../templates-hidden/default-header.html | 6 +- .../main/webapp/templates-hidden/default.html | 6 +- .../test/scala/code/util/OAuthClient.scala | 2 +- 15 files changed, 73 insertions(+), 219 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index dc558759a..8bc5aa02c 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -569,15 +569,16 @@ webui_oauth_1_documentation_url = # Link to OAuth 2.0 glossary on api explorer webui_oauth_2_documentation_url = -# Link to Privacy Policy on signup page -#webui_signup_form_submit_button_value= -#webui_signup_form_title_text=Sign Up -#webui_signup_body_password_repeat_text=Repeat -#allow_pre_filled_password=true -#webui_agree_terms_html=
-webui_agree_privacy_policy_url = https://openbankproject.com/privacy-policy -webui_agree_privacy_policy_html_text =
-#webui_legal_notice_html_text= +# Sign up functionality removed - users are directed to OBP Portal for registration +# The following signup-related properties are no longer used: +# - webui_signup_form_submit_button_value (signup form submit button text) +# - webui_signup_form_title_text (signup form title) +# - webui_signup_body_password_repeat_text (password repeat field text) +# - allow_pre_filled_password (pre-filled password functionality) +# - webui_agree_terms_html (terms agreement checkbox HTML) +# - webui_agree_privacy_policy_url (privacy policy URL for signup) +# - webui_agree_privacy_policy_html_text (privacy policy agreement text) +# - webui_legal_notice_html_text (legal notice for signup forms) ## For partner logos and links webui_main_partners=[\ @@ -596,8 +597,8 @@ webui_main_style_sheet = /media/css/website.css # Override certain elements (with important styles) webui_override_style_sheet = -## Link to agree to Terms & Conditions, shown on signup page -webui_agree_terms_url = +## Link to agree to Terms & Conditions (no longer used - signup removed) +# webui_agree_terms_url = ## The Support Email, shown in the bottom page #webui_support_email=contact@openbankproject.com @@ -625,6 +626,9 @@ webui_agree_terms_url = #webui_post_consumer_registration_submit_button_value=Register consumer # OBP Portal URL - base URL for the OBP Portal service +# Used for: +# - User registration: {webui_obp_portal_url}/register (all "Register" links redirect here) +# - Consumer registration: {webui_obp_portal_url}/consumer-registration (default) webui_obp_portal_url = http://localhost:5174 # External Consumer Registration URL - used to redirect "Get API Key" links to an external service diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 79d3ff77c..b0c0dc2ca 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -1095,7 +1095,7 @@ object Glossary extends MdcLoggable { | |### 1) Get your App key | - |[Sign up]($getServerUrl/user_mgt/sign_up) or [login]($getServerUrl/user_mgt/login) as a developer. + |[Sign up](${APIUtil.getPropsValue("webui_obp_portal_url", "http://localhost:5174")}/register) or [login]($getServerUrl/user_mgt/login) as a developer. | |Register your App key [HERE](${getConsumerRegistrationUrl()}) | @@ -2151,7 +2151,7 @@ object Glossary extends MdcLoggable { | |### Step 1: Get your App key | - |[Sign up]($getServerUrl/user_mgt/sign_up) or [login]($getServerUrl/user_mgt/login) as a developer + |[Sign up](${APIUtil.getPropsValue("webui_obp_portal_url", "http://localhost:5174")}/register) or [login]($getServerUrl/user_mgt/login) as a developer | |Register your App key [HERE](${getConsumerRegistrationUrl()}) | @@ -2800,7 +2800,7 @@ object Glossary extends MdcLoggable { | |## In order to get an App / Consumer key | -|[Sign up]($getServerUrl/user_mgt/sign_up) or [login]($getServerUrl/user_mgt/login) as a developer. +|[Sign up](${APIUtil.getPropsValue("webui_obp_portal_url", "http://localhost:5174")}/register) or [login]($getServerUrl/user_mgt/login) as a developer. | |Register your App / Consumer [HERE](${getConsumerRegistrationUrl()}) | diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 0d8a462f9..ee6d171a3 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -229,7 +229,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with CreatedUpdated with MdcLogga override lazy val password = new MyPasswordNew - lazy val signupPasswordRepeatText = getWebUiPropsValue("webui_signup_body_password_repeat_text", S.?("repeat")) + // Removed signup password repeat text - not needed with OBP Portal redirect class MyPasswordNew extends MappedPassword(this) { lazy val preFilledPassword = if (APIUtil.getPropsAsBoolValue("allow_pre_filled_password", true)) {get.toString} else "" @@ -238,14 +238,9 @@ class AuthUser extends MegaProtoUser[AuthUser] with CreatedUpdated with MdcLogga Full( {appendFieldId( ) } -
+
-
{signupPasswordRepeatText}
- -
- -
) } } @@ -429,7 +424,6 @@ import net.liftweb.util.Helpers._ override def screenWrap = Full() // define the order fields will appear in forms and output override def fieldOrder = List(id, firstName, lastName, email, username, password, provider) - override def signupFields = List(firstName, lastName, email, username, password) // To force validation of email addresses set this to false (default as of 29 June 2021) override def skipEmailValidation = APIUtil.getPropsAsBoolValue("authUser.skipEmailValidation", false) @@ -698,28 +692,7 @@ import net.liftweb.util.Helpers._ case _ => S.error(S.?("invalid.validation.link")); S.redirectTo(homePage) } - override def actionsAfterSignup(theUser: TheUserType, func: () => Nothing): Nothing = { - theUser.setValidated(skipEmailValidation).resetUniqueId() - theUser.save - val privacyPolicyValue: String = getWebUiPropsValue("webui_privacy_policy", "") - val termsAndConditionsValue: String = getWebUiPropsValue("webui_terms_and_conditions", "") - // User Agreement table - UserAgreementProvider.userAgreementProvider.vend.createUserAgreement( - theUser.user.foreign.map(_.userId).getOrElse(""), "privacy_conditions", privacyPolicyValue) - UserAgreementProvider.userAgreementProvider.vend.createUserAgreement( - theUser.user.foreign.map(_.userId).getOrElse(""), "terms_and_conditions", termsAndConditionsValue) - if (!skipEmailValidation) { - sendValidationEmail(theUser) - S.notice(S.?("sign.up.message")) - func() - } else { - grantDefaultEntitlementsToAuthUser(theUser) - logUserIn(theUser, () => { - S.notice(S.?("welcome")) - func() - }) - } - } + /** * Set this to redirect to a certain page after a failed login */ @@ -728,87 +701,9 @@ import net.liftweb.util.Helpers._ } - def agreeTermsDiv = { - val webUi = new WebUI - val webUiPropsValue = getWebUiPropsValue("webui_terms_and_conditions", "") - val termsAndConditionsCheckboxTitle = Helper.i18n("terms_and_conditions_checkbox_text", Some("I agree to the above Terms and Conditions")) - val termsAndConditionsCheckboxLabel = Helper.i18n("terms_and_conditions_checkbox_label", Some("Terms and Conditions")) - val agreeTermsHtml = s"""
- |
- |
- | $termsAndConditionsCheckboxLabel - |
${webUi.makeHtml(webUiPropsValue)}
- |
- | - | - |
- | """.stripMargin - - scala.xml.Unparsed(agreeTermsHtml) - } - - def legalNoticeDiv = { - val agreeTermsHtml = getWebUiPropsValue("webui_legal_notice_html_text", "") - if(agreeTermsHtml.isEmpty){ - s"" - } else{ - scala.xml.Unparsed(s"""$agreeTermsHtml""") - } - } - - def agreePrivacyPolicy = { - val webUi = new WebUI - val privacyPolicyCheckboxText = Helper.i18n("privacy_policy_checkbox_text", Some("I agree to the above Privacy Policy")) - val privacyPolicyCheckboxLabel = Helper.i18n("privacy_policy_checkbox_label", Some("Privacy Policy")) - val webUiPropsValue = getWebUiPropsValue("webui_privacy_policy", "") - val agreePrivacyPolicy = s"""
- |
- |
- | $privacyPolicyCheckboxLabel - |
${webUi.makeHtml(webUiPropsValue)}
- |
- | - | - |
- |
""".stripMargin - - scala.xml.Unparsed(agreePrivacyPolicy) - } - def enableDisableSignUpButton = { - val javaScriptCode = """""".stripMargin - - scala.xml.Unparsed(javaScriptCode) - } - - def signupFormTitle = getWebUiPropsValue("webui_signup_form_title_text", S.?("sign.up")) - - override def signupXhtml (user:AuthUser) = { -
-
-

{signupFormTitle}

- {legalNoticeDiv} -
- {localForm(user, false, signupFields)} - {agreeTermsDiv} - {agreePrivacyPolicy} -
- -
- {enableDisableSignUpButton} -
-
- } + // Removed signup-related methods: agreeTermsDiv, legalNoticeDiv, agreePrivacyPolicy + // These were only used in signup forms which now redirect to OBP Portal + // Signup functionality removed - users are directed to OBP Portal for registration override def localForm(user: TheUserType, ignorePassword: Boolean, fields: List[FieldPointerType]): NodeSeq = { @@ -818,18 +713,11 @@ import net.liftweb.util.Helpers._ if field.show_? && (!ignorePassword || !pointer.isPasswordField_?) form <- field.toForm.toList } yield { - if(field.uniqueFieldId.getOrElse("") == "authuser_password") { -
- - {form} -
- } else { -
- - {form} -
-
- } +
+ + {form} +
+
} } @@ -1610,67 +1498,8 @@ def restoreSomeSessions(): Unit = { val usernames: List[String] = this.getResourceUsersByEmail(email).map(_.user.name) findAll(ByList(this.username, usernames)) } - def signupSubmitButtonValue() = getWebUiPropsValue("webui_signup_form_submit_button_value", S.?("sign.up")) - //overridden to allow redirect to loginRedirect after signup. This is mostly to allow - // loginFirst menu items to work if the user doesn't have an account. Without this, - // if a user tries to access a logged-in only page, and then signs up, they don't get redirected - // back to the proper page. - override def signup = { - val theUser: TheUserType = mutateUserOnSignup(createNewUserInstance()) - val theName = signUpPath.mkString("") - //Check the internal redirect, in case for open redirect issue. - // variable redir is from loginRedirect, it is set-up in OAuthAuthorisation.scala as following code: - // val currentUrl = ObpS.uriAndQueryString.getOrElse("/") - // AuthUser.loginRedirect.set(Full(Helpers.appendParams(currentUrl, List((LogUserOutParam, "false"))))) - val loginRedirectSave = loginRedirect.is - - def testSignup() { - validateSignup(theUser) match { - case Nil => - //here we check loginRedirectSave (different from implementation in super class) - val redir = loginRedirectSave match { - case Full(url) => - loginRedirect(Empty) - url - case _ => - //if the register page url (user_mgt/sign_up?after-signup=link-to-customer) contains the parameter - //after-signup=link-to-customer,then it will redirect to the on boarding customer page. - ObpS.param("after-signup") match { - case url if (url.equals("link-to-customer")) => - "/add-user-auth-context-update-request" - case _ => - homePage - } - } - if (Helper.isValidInternalRedirectUrl(redir.toString)) { - actionsAfterSignup(theUser, () => { - S.redirectTo(redir) - }) - } else { - S.error(S.?(ErrorMessages.InvalidInternalRedirectUrl)) - logger.info(ErrorMessages.InvalidInternalRedirectUrl + loginRedirect.get) - } - - case xs => - xs.foreach{ - e => S.error(e.field.uniqueFieldId.openOrThrowException("There is no uniqueFieldId."), e.msg) - } - signupFunc(Full(innerSignup _)) - } - } - - def innerSignup = { - val bind = "type=submit" #> signupSubmitButton(signupSubmitButtonValue(), testSignup _) - bind(signupXhtml(theUser)) - } - - if(APIUtil.getPropsAsBoolValue("user_invitation.mandatory", false)) - S.redirectTo("/user-invitation-info") - else - innerSignup - } def scrambleAuthUser(userPrimaryKey: UserPrimaryKey): Box[Boolean] = tryo { AuthUser.find(By(AuthUser.user, userPrimaryKey.value)) match { diff --git a/obp-api/src/main/scala/code/snippet/Login.scala b/obp-api/src/main/scala/code/snippet/Login.scala index a7c6a36c3..1ae8ce83b 100644 --- a/obp-api/src/main/scala/code/snippet/Login.scala +++ b/obp-api/src/main/scala/code/snippet/Login.scala @@ -70,8 +70,11 @@ class Login { href getOrElse "#" } & { ".signup [href]" #> { - AuthUser.signUpPath.foldLeft("")(_ + "/" + _) - } + val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") + s"$portalUrl/register" + } & + ".signup [target]" #> "_blank" & + ".signup [rel]" #> "noopener" } } } diff --git a/obp-api/src/main/scala/code/snippet/OAuthAuthorisation.scala b/obp-api/src/main/scala/code/snippet/OAuthAuthorisation.scala index 66a598627..be038b035 100644 --- a/obp-api/src/main/scala/code/snippet/OAuthAuthorisation.scala +++ b/obp-api/src/main/scala/code/snippet/OAuthAuthorisation.scala @@ -46,6 +46,7 @@ import net.liftweb.http.S import net.liftweb.util.Helpers._ import net.liftweb.util.{CssSel, Helpers, Props} import code.api.oauth1a.OauthParams._ +import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import scala.xml.NodeSeq @@ -150,8 +151,12 @@ object OAuthAuthorisation { href getOrElse "#" } & - ".signup [href]" #> - AuthUser.signUpPath.foldLeft("")(_ + "/" + _) + ".signup [href]" #> { + val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") + s"$portalUrl/register" + } & + ".signup [target]" #> "_blank" & + ".signup [rel]" #> "noopener" } } case _ => error("Application not found") diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index d732bbec2..c741558c5 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -550,8 +550,21 @@ class WebUI extends MdcLoggable{ def userIsLoggedIn: CssSel = { if(AuthUser.loggedIn_?) "#register-link [href]" #> scala.xml.Unparsed(s"/already-logged-in") - else - "#register-link [href]" #> scala.xml.Unparsed(s"/user_mgt/sign_up") + else { + val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") + val registerUrl = s"$portalUrl/register" + "#register-link [href]" #> scala.xml.Unparsed(registerUrl) & + "#register-link [target]" #> "_blank" & + "#register-link [rel]" #> "noopener" + } + } + + def portalRegisterLink: CssSel = { + val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") + val registerUrl = s"$portalUrl/register" + "a [href]" #> scala.xml.Unparsed(registerUrl) & + "a [target]" #> "_blank" & + "a [rel]" #> "noopener" } def alreadyLoggedIn: CssSel = { diff --git a/obp-api/src/main/webapp/index-en.html b/obp-api/src/main/webapp/index-en.html index a0dd0210c..32075b8b4 100644 --- a/obp-api/src/main/webapp/index-en.html +++ b/obp-api/src/main/webapp/index-en.html @@ -59,7 +59,7 @@ Berlin 13359, Germany

-

+

.

diff --git a/obp-api/src/main/webapp/index.html b/obp-api/src/main/webapp/index.html index 54b4d75a3..92fabd6ba 100644 --- a/obp-api/src/main/webapp/index.html +++ b/obp-api/src/main/webapp/index.html @@ -59,7 +59,7 @@ Berlin 13359, Germany

Create an account

-

First, create a free developer account on this sandbox and request a developer key. You will be asked to submit basic information about your app at this stage. Register for an account +

First, create a free developer account on this sandbox and request a developer key. You will be asked to submit basic information about your app at this stage. Register for an account .

diff --git a/obp-api/src/main/webapp/oauth/authorize.html b/obp-api/src/main/webapp/oauth/authorize.html index b4d7678a0..a71babac7 100644 --- a/obp-api/src/main/webapp/oauth/authorize.html +++ b/obp-api/src/main/webapp/oauth/authorize.html @@ -40,7 +40,7 @@
Don't have an account? - Register + Register
diff --git a/obp-api/src/main/webapp/templates-hidden/_login.html b/obp-api/src/main/webapp/templates-hidden/_login.html index c96de62e2..0b91a507c 100644 --- a/obp-api/src/main/webapp/templates-hidden/_login.html +++ b/obp-api/src/main/webapp/templates-hidden/_login.html @@ -42,7 +42,7 @@
Don't have an account? - Register + Register
diff --git a/obp-api/src/main/webapp/templates-hidden/default-en.html b/obp-api/src/main/webapp/templates-hidden/default-en.html index 2b2e4f831..9da6dba6d 100644 --- a/obp-api/src/main/webapp/templates-hidden/default-en.html +++ b/obp-api/src/main/webapp/templates-hidden/default-en.html @@ -143,7 +143,7 @@ Berlin 13359, Germany @@ -198,7 +198,7 @@ Berlin 13359, Germany
  • @@ -235,7 +235,7 @@ Berlin 13359, Germany Sofit
  • - + On Board
  • diff --git a/obp-api/src/main/webapp/templates-hidden/default-footer.html b/obp-api/src/main/webapp/templates-hidden/default-footer.html index 74a60838b..819ba810c 100644 --- a/obp-api/src/main/webapp/templates-hidden/default-footer.html +++ b/obp-api/src/main/webapp/templates-hidden/default-footer.html @@ -148,7 +148,7 @@ Berlin 13359, Germany
  • @@ -208,7 +208,7 @@ Berlin 13359, Germany
  • @@ -248,7 +248,7 @@ Berlin 13359, Germany Sofit
  • - + On Board
  • diff --git a/obp-api/src/main/webapp/templates-hidden/default-header.html b/obp-api/src/main/webapp/templates-hidden/default-header.html index fba6bbb16..c5079d3d9 100644 --- a/obp-api/src/main/webapp/templates-hidden/default-header.html +++ b/obp-api/src/main/webapp/templates-hidden/default-header.html @@ -143,7 +143,7 @@ Berlin 13359, Germany
  • @@ -198,7 +198,7 @@ Berlin 13359, Germany
  • @@ -236,7 +236,7 @@ Berlin 13359, Germany Sofit
  • - + On Board
  • diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index 4eb5915ca..c2ec26e45 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -143,7 +143,7 @@ Berlin 13359, Germany
  • @@ -198,7 +198,7 @@ Berlin 13359, Germany
  • @@ -235,7 +235,7 @@ Berlin 13359, Germany Sofit
  • - + On Board
  • diff --git a/obp-api/src/test/scala/code/util/OAuthClient.scala b/obp-api/src/test/scala/code/util/OAuthClient.scala index d930f85ee..4f81b1ad4 100644 --- a/obp-api/src/test/scala/code/util/OAuthClient.scala +++ b/obp-api/src/test/scala/code/util/OAuthClient.scala @@ -67,7 +67,7 @@ trait DefaultProvider extends Provider { val requestTokenUrl = baseUrl + "/oauth/initiate" val accessTokenUrl = baseUrl + "/oauth/token" val authorizeUrl = baseUrl + "/oauth/authorize" - val signupUrl = Some(baseUrl + "/user_mgt/sign_up") + val signupUrl = Some(APIUtil.getPropsValue("webui_obp_portal_url", "http://localhost:5174") + "/register") lazy val oAuthProvider : OAuthProvider = new DefaultOAuthProvider(requestTokenUrl, accessTokenUrl, authorizeUrl) From 0fcf0b9d457d820c475915d028a6d6cd07021103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 23 Dec 2025 10:34:17 +0100 Subject: [PATCH 04/48] feature/Reduce test warnings --- obp-api/src/test/scala/RunMTLSWebApp.scala | 2 +- obp-api/src/test/scala/RunTLSWebApp.scala | 2 +- obp-api/src/test/scala/code/AppTest.scala | 22 +++++++-------- .../test/scala/code/api/DirectLoginTest.scala | 1 + .../scala/code/api/OBPRestHelperTest.scala | 1 - .../ResourceDocs1_4_0/ResourceDocsTest.scala | 1 + .../ResourceDocs1_4_0/SwaggerDocsTest.scala | 1 + .../code/api/util/JavaWebSignatureTest.scala | 1 + .../scala/code/api/v1_4_0/BranchesTest.scala | 2 ++ .../v2_1_0/CreateTransactionTypeTest.scala | 1 + .../code/api/v2_1_0/EntitlementTests.scala | 1 + .../scala/code/api/v2_2_0/API2_2_0Test.scala | 14 ++++++++++ .../code/api/v2_2_0/ExchangeRateTest.scala | 10 +++++++ .../scala/code/api/v3_0_0/AccountTest.scala | 9 +++++++ .../scala/code/api/v3_0_0/BranchesTest.scala | 4 +++ .../code/api/v3_0_0/CounterpartyTest.scala | 5 ++++ .../api/v3_0_0/EntitlementRequestsTest.scala | 10 +++++++ .../scala/code/api/v3_0_0/FirehoseTest.scala | 11 ++++++++ .../code/api/v3_0_0/GetAdapterInfoTest.scala | 10 +++++++ .../code/api/v3_0_0/TransactionsTest.scala | 8 ++++++ .../test/scala/code/api/v3_0_0/UserTest.scala | 15 +++++++++++ .../scala/code/api/v3_0_0/ViewsTests.scala | 15 +++++++++++ .../scala/code/api/v3_0_0/WarehouseTest.scala | 10 +++++++ .../code/api/v3_0_0/WarehouseTestAsync.scala | 11 ++++++++ .../scala/code/api/v3_1_0/AccountTest.scala | 25 +++++++++++++++++ .../scala/code/api/v3_1_0/ConsentTest.scala | 16 +++++++++++ .../code/api/v3_1_0/TransactionTest.scala | 8 +++--- .../scala/code/api/v4_0_0/AccountTest.scala | 2 +- .../AuthenticationTypeValidationTest.scala | 15 +++++++++++ .../code/api/v4_0_0/ConnectorMethodTest.scala | 2 +- .../api/v4_0_0/ForceErrorValidationTest.scala | 16 +++++++++++ .../api/v4_0_0/JsonSchemaValidationTest.scala | 15 +++++++++++ .../api/v4_0_0/TransactionRequestsTest.scala | 4 +-- .../scala/code/api/v5_0_0/AccountTest.scala | 24 +++++++++++++++++ .../scala/code/api/v5_0_0/ViewsTests.scala | 10 +++++++ .../code/api/v5_1_0/ConsentObpTest.scala | 16 +++++++++++ .../api/v5_1_0/VRPConsentRequestTest.scala | 27 +++++++++++++++++++ .../scala/code/api/v6_0_0/CustomerTest.scala | 2 +- .../code/api/v6_0_0/PasswordResetTest.scala | 2 +- .../scala/code/connector/ConnectorTest.scala | 9 +++++++ .../connector/InternalConnectorTest.scala | 1 + .../scala/code/connector/MessageDocTest.scala | 1 + .../RestConnector_vMar2019_FrozenTest.scala | 1 + .../scala/code/util/FrozenClassUtil.scala | 1 + 44 files changed, 338 insertions(+), 26 deletions(-) diff --git a/obp-api/src/test/scala/RunMTLSWebApp.scala b/obp-api/src/test/scala/RunMTLSWebApp.scala index 06381729b..6169fd19b 100644 --- a/obp-api/src/test/scala/RunMTLSWebApp.scala +++ b/obp-api/src/test/scala/RunMTLSWebApp.scala @@ -89,7 +89,7 @@ object RunMTLSWebApp extends App with PropsProgrammatically { // RESET HEADER https.addCustomizer(customizer) - val sslContextFactory = new SslContextFactory() + val sslContextFactory = new SslContextFactory.Server() sslContextFactory.setKeyStorePath(this.getClass.getResource("/cert/server.jks").toExternalForm) sslContextFactory.setKeyStorePassword("123456") diff --git a/obp-api/src/test/scala/RunTLSWebApp.scala b/obp-api/src/test/scala/RunTLSWebApp.scala index dc4f7afff..718734b5a 100644 --- a/obp-api/src/test/scala/RunTLSWebApp.scala +++ b/obp-api/src/test/scala/RunTLSWebApp.scala @@ -89,7 +89,7 @@ object RunTLSWebApp extends App with PropsProgrammatically { // RESET HEADER https.addCustomizer(customizer) - val sslContextFactory = new SslContextFactory() + val sslContextFactory = new SslContextFactory.Server() sslContextFactory.setKeyStorePath(this.getClass.getResource("/cert/server.jks").toExternalForm) sslContextFactory.setKeyStorePassword("123456") diff --git a/obp-api/src/test/scala/code/AppTest.scala b/obp-api/src/test/scala/code/AppTest.scala index 2e8dedba9..20c50420c 100644 --- a/obp-api/src/test/scala/code/AppTest.scala +++ b/obp-api/src/test/scala/code/AppTest.scala @@ -27,33 +27,29 @@ TESOBE (http://www.tesobe.com/) package code import java.io.File -import junit.framework._ -import Assert._ import scala.xml.XML import net.liftweb.util._ import net.liftweb.common._ +import org.scalatest.{FlatSpec, Matchers} object AppTest { - def suite: Test = { - val suite = new TestSuite(classOf[AppTest]) - suite - } - def main(args : Array[String]) { - junit.textui.TestRunner.run(suite) + // Use ScalaTest runner instead + println("Use 'sbt test' or 'mvn test' to run tests") } } /** * Unit test for simple App. */ -class AppTest extends TestCase("app") { +class AppTest extends FlatSpec with Matchers { /** - * Rigourous Tests :-) + * Basic functionality test */ - def testOK() = assertTrue(true) - // def testKO() = assertTrue(false); + "App" should "pass basic test" in { + true should be(true) + } /** * Tests to make sure the project's XML files are well-formed. @@ -61,7 +57,7 @@ class AppTest extends TestCase("app") { * Finds every *.html and *.xml file in src/main/webapp (and its * subdirectories) and tests to make sure they are well-formed. */ - def testXml() = { + it should "have well-formed XML files" in { var failed: List[File] = Nil def handledXml(file: String) = diff --git a/obp-api/src/test/scala/code/api/DirectLoginTest.scala b/obp-api/src/test/scala/code/api/DirectLoginTest.scala index 2cb1c92c3..9cca2d5e4 100644 --- a/obp-api/src/test/scala/code/api/DirectLoginTest.scala +++ b/obp-api/src/test/scala/code/api/DirectLoginTest.scala @@ -13,6 +13,7 @@ import code.setup.{APIResponse, ServerSetup, TestPasswordConfig} import code.userlocks.UserLocksProvider import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion import net.liftweb.json.JsonAST.{JArray, JField, JObject, JString} import net.liftweb.mapper.By diff --git a/obp-api/src/test/scala/code/api/OBPRestHelperTest.scala b/obp-api/src/test/scala/code/api/OBPRestHelperTest.scala index a8bfc06c1..ddc90c77b 100644 --- a/obp-api/src/test/scala/code/api/OBPRestHelperTest.scala +++ b/obp-api/src/test/scala/code/api/OBPRestHelperTest.scala @@ -1,7 +1,6 @@ package code.api import code.api.util.APIUtil.{ResourceDoc, EmptyBody} -import code.api.OBPRestHelper import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} import org.scalatest.{FlatSpec, Matchers, Tag} diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index a83097685..e758d413e 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -9,6 +9,7 @@ import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocsJson import code.setup.{DefaultUsers, PropsReset} import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.{ApiVersion, Functions} +import scala.language.reflectiveCalls import net.liftweb.json import net.liftweb.json.JsonAST._ import net.liftweb.json.{Formats, JString, Serializer, TypeInfo} diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerDocsTest.scala index b96a1acf3..2fe764ed5 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerDocsTest.scala @@ -5,6 +5,7 @@ import code.api.util.{ApiRole, CustomJsonFormats} import code.setup.{DefaultUsers, PropsReset} import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.{ApiVersion, Functions} +import scala.language.reflectiveCalls import io.swagger.parser.OpenAPIParser import net.liftweb.json import net.liftweb.json.JsonAST._ diff --git a/obp-api/src/test/scala/code/api/util/JavaWebSignatureTest.scala b/obp-api/src/test/scala/code/api/util/JavaWebSignatureTest.scala index f62967346..837542615 100644 --- a/obp-api/src/test/scala/code/api/util/JavaWebSignatureTest.scala +++ b/obp-api/src/test/scala/code/api/util/JavaWebSignatureTest.scala @@ -11,6 +11,7 @@ import com.github.dwickern.macros.NameOf.nameOf import net.liftweb.common.Full import net.liftweb.util.Helpers._ import org.scalatest.Tag +import scala.language.postfixOps class JavaWebSignatureTest extends V400ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v1_4_0/BranchesTest.scala b/obp-api/src/test/scala/code/api/v1_4_0/BranchesTest.scala index e9d6239ca..5eefca75e 100644 --- a/obp-api/src/test/scala/code/api/v1_4_0/BranchesTest.scala +++ b/obp-api/src/test/scala/code/api/v1_4_0/BranchesTest.scala @@ -1,4 +1,6 @@ package code.api.v1_4_0 +// Note: This test intentionally uses deprecated model classes (LobbyStringT, DriveUpStringT) +// to maintain backwards compatibility testing. These warnings are expected. import code.api.util.APIUtil.OAuth._ import code.api.util.OBPQueryParam diff --git a/obp-api/src/test/scala/code/api/v2_1_0/CreateTransactionTypeTest.scala b/obp-api/src/test/scala/code/api/v2_1_0/CreateTransactionTypeTest.scala index 8a0bedf9b..f2d1c0d06 100644 --- a/obp-api/src/test/scala/code/api/v2_1_0/CreateTransactionTypeTest.scala +++ b/obp-api/src/test/scala/code/api/v2_1_0/CreateTransactionTypeTest.scala @@ -10,6 +10,7 @@ import code.setup.DefaultUsers import code.transaction_types.MappedTransactionType import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model.{AmountOfMoneyJsonV121, ErrorMessage, TransactionTypeId} +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion import net.liftweb.json.Serialization._ import org.scalatest.Tag diff --git a/obp-api/src/test/scala/code/api/v2_1_0/EntitlementTests.scala b/obp-api/src/test/scala/code/api/v2_1_0/EntitlementTests.scala index 0267f559e..ecec7ea29 100644 --- a/obp-api/src/test/scala/code/api/v2_1_0/EntitlementTests.scala +++ b/obp-api/src/test/scala/code/api/v2_1_0/EntitlementTests.scala @@ -10,6 +10,7 @@ import code.entitlement.Entitlement import code.setup.DefaultUsers import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import org.scalatest.Tag diff --git a/obp-api/src/test/scala/code/api/v2_2_0/API2_2_0Test.scala b/obp-api/src/test/scala/code/api/v2_2_0/API2_2_0Test.scala index 34e50d2b3..c7b1deebc 100644 --- a/obp-api/src/test/scala/code/api/v2_2_0/API2_2_0Test.scala +++ b/obp-api/src/test/scala/code/api/v2_2_0/API2_2_0Test.scala @@ -27,20 +27,34 @@ TESOBE (http://www.tesobe.com/) package code.api.v2_2_0 import code.api.Constant._ +import scala.language.reflectiveCalls import _root_.net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJsonV300 +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.v1_2._ +import scala.language.reflectiveCalls import code.api.v1_2_1.UpdateViewJsonV121 +import scala.language.reflectiveCalls import code.setup.{APIResponse, DefaultUsers} +import scala.language.reflectiveCalls import com.openbankproject.commons.model.CreateViewJson +import scala.language.reflectiveCalls import net.liftweb.util.Helpers._ +import scala.language.reflectiveCalls import org.scalatest._ +import scala.language.reflectiveCalls import code.api.v2_2_0.OBPAPI2_2_0.Implementations2_2_0 +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import scala.util.Random._ +import scala.language.reflectiveCalls class API2_2_0Test extends V220ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v2_2_0/ExchangeRateTest.scala b/obp-api/src/test/scala/code/api/v2_2_0/ExchangeRateTest.scala index 2b9896867..aaf37c2a1 100644 --- a/obp-api/src/test/scala/code/api/v2_2_0/ExchangeRateTest.scala +++ b/obp-api/src/test/scala/code/api/v2_2_0/ExchangeRateTest.scala @@ -1,15 +1,25 @@ package code.api.v2_2_0 import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.InvalidISOCurrencyCode +import scala.language.reflectiveCalls import code.consumer.Consumers +import scala.language.reflectiveCalls import code.scope.Scope +import scala.language.reflectiveCalls import code.setup.DefaultUsers +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class ExchangeRateTest extends V220ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/AccountTest.scala index d7d759406..849bdd74a 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/AccountTest.scala @@ -1,14 +1,23 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole.CanUseAccountFirehoseAtAnyBank +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{AccountFirehoseNotAllowedOnThisInstance, UserHasMissingRoles} +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.setup.APIResponse +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class AccountTest extends V300ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v3_0_0/BranchesTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/BranchesTest.scala index 579b8e4d8..ce4253ca3 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/BranchesTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/BranchesTest.scala @@ -1,4 +1,6 @@ package code.api.v3_0_0 +// Note: This test intentionally uses deprecated model classes (LobbyStringT, DriveUpStringT) +// to maintain backwards compatibility testing. These warnings are expected. import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole.CanDeleteBranchAtAnyBank @@ -13,6 +15,8 @@ import code.setup.DefaultUsers import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model._ import org.scalatest.Tag +import scala.language.postfixOps +import scala.language.reflectiveCalls import scala.concurrent.duration._ import scala.concurrent.Await diff --git a/obp-api/src/test/scala/code/api/v3_0_0/CounterpartyTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/CounterpartyTest.scala index 1dc35fe80..ece6cb43a 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/CounterpartyTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/CounterpartyTest.scala @@ -1,10 +1,15 @@ package code.api.v3_0_0 import code.api.Constant._ +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class CounterpartyTest extends V300ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v3_0_0/EntitlementRequestsTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/EntitlementRequestsTest.scala index 47417995d..f763fcf75 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/EntitlementRequestsTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/EntitlementRequestsTest.scala @@ -1,15 +1,25 @@ package code.api.v3_0_0 import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole.{CanGetEntitlementRequestsAtAnyBank} +import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ +import scala.language.reflectiveCalls import code.api.util.{ApiRole} +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.DefaultUsers +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls /* Note This does not test retrieval from a backend. diff --git a/obp-api/src/test/scala/code/api/v3_0_0/FirehoseTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/FirehoseTest.scala index 45e6b1b36..1d50e0bbe 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/FirehoseTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/FirehoseTest.scala @@ -1,16 +1,27 @@ package code.api.v3_0_0 import code.api.Constant +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole +import scala.language.reflectiveCalls import code.api.util.ApiRole.{CanUseAccountFirehose, CanUseAccountFirehoseAtAnyBank} +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.AccountFirehoseNotAllowedOnThisInstance +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.PropsReset +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class FirehoseTest extends V300ServerSetup with PropsReset{ /** diff --git a/obp-api/src/test/scala/code/api/v3_0_0/GetAdapterInfoTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/GetAdapterInfoTest.scala index c3c7a1e0f..a363ee261 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/GetAdapterInfoTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/GetAdapterInfoTest.scala @@ -26,15 +26,25 @@ TESOBE (http://www.tesobe.com/) package code.api.v3_0_0 import code.api.util.ApiRole.canGetAdapterInfoAtOneBank +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.DefaultUsers +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class GetAdapterInfoTest extends V300ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/TransactionsTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/TransactionsTest.scala index 487c22e05..66e250d6b 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/TransactionsTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/TransactionsTest.scala @@ -1,13 +1,21 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole.CanUseAccountFirehoseAtAnyBank +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{AccountFirehoseNotAllowedOnThisInstance, UserHasMissingRoles} +import scala.language.reflectiveCalls import code.api.util.{APIUtil, ErrorMessages} +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class TransactionsTest extends V300ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/UserTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/UserTest.scala index bc0ade496..4eccea066 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/UserTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/UserTest.scala @@ -1,20 +1,35 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.{ApiRole, ErrorMessages} +import scala.language.reflectiveCalls import code.api.util.ApiRole.CanGetAnyUser +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.UserHasMissingRoles +import scala.language.reflectiveCalls import code.api.v2_0_0.JSONFactory200.UsersJsonV200 +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.DefaultUsers +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json.JsonAST._ +import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import net.liftweb.util.Helpers.randomString +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class UserTest extends V300ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/ViewsTests.scala b/obp-api/src/test/scala/code/api/v3_0_0/ViewsTests.scala index 1d6df40d9..b567b3aa6 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/ViewsTests.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/ViewsTests.scala @@ -27,21 +27,36 @@ TESOBE (http://www.tesobe.com/) package code.api.v3_0_0 import code.api.Constant._ +import scala.language.reflectiveCalls import _root_.net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import code.api.v1_2_1.{APIInfoJSON, PermissionJSON, PermissionsJSON} +import scala.language.reflectiveCalls import code.api.v2_2_0.{ViewJSONV220, ViewsJSONV220} +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.setup.APIResponse +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.{CreateViewJson, UpdateViewJSON} +import scala.language.reflectiveCalls import net.liftweb.util.Helpers._ +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls import scala.util.Random.nextInt +import scala.language.reflectiveCalls class ViewsTests extends V300ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTest.scala index 3a88f90f2..00a364994 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTest.scala @@ -3,15 +3,25 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole.CanSearchWarehouse +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.UserHasMissingRoles +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.setup.{APIResponse, DefaultUsers} +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class WarehouseTest extends V300ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTestAsync.scala b/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTestAsync.scala index 6d0ee3188..9dfa99f9b 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTestAsync.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTestAsync.scala @@ -3,17 +3,28 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole.CanSearchWarehouse +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.UserHasMissingRoles +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.setup.{APIResponse, DefaultUsers} +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls import scala.concurrent.Future +import scala.language.reflectiveCalls class WarehouseTestAsync extends V300ServerSetupAsync with DefaultUsers { /** diff --git a/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala index 68c6e0046..94db2bbb5 100644 --- a/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala @@ -1,31 +1,56 @@ package code.api.v3_1_0 import code.api.Constant +import scala.language.reflectiveCalls import com.openbankproject.commons.model.{AccountRouting, AccountRoutingJsonV121, AmountOfMoneyJsonV121, ErrorMessage, enums} +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.updateAccountRequestJsonV310 +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.APIUtil.extractErrorMessageCode +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} +import scala.language.reflectiveCalls import code.api.util.ApiRole +import scala.language.reflectiveCalls import code.api.v2_0_0.BasicAccountJSON +import scala.language.reflectiveCalls import code.api.v2_2_0.CreateAccountJSONV220 +import scala.language.reflectiveCalls import code.api.v3_0_0.{CoreAccountsJsonV300, ModeratedCoreAccountJsonV300} +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 +import scala.language.reflectiveCalls import code.api.v2_0_0.OBPAPI2_0_0.Implementations2_0_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.model.dataAccess.BankAccountRouting +import scala.language.reflectiveCalls import code.setup.DefaultUsers +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.enums.AccountRoutingScheme +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls import java.util.UUID +import scala.language.reflectiveCalls import java.util.concurrent.TimeUnit +import scala.language.reflectiveCalls import scala.util.Random +import scala.language.reflectiveCalls class AccountTest extends V310ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_1_0/ConsentTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/ConsentTest.scala index 894c29dbb..1b9db56e1 100644 --- a/obp-api/src/test/scala/code/api/v3_1_0/ConsentTest.scala +++ b/obp-api/src/test/scala/code/api/v3_1_0/ConsentTest.scala @@ -26,22 +26,38 @@ TESOBE (http://www.tesobe.com/) package code.api.v3_1_0 import code.api.Constant +import scala.language.reflectiveCalls import code.api.RequestHeader +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import scala.language.reflectiveCalls import code.api.util.{APIUtil, Consent} +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole._ +import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ +import scala.language.reflectiveCalls import code.api.v3_0_0.{APIMethods300, UserJsonV300} +import scala.language.reflectiveCalls import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls import java.util.Date +import scala.language.reflectiveCalls class ConsentTest extends V310ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v3_1_0/TransactionTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/TransactionTest.scala index f67ddc624..8a5b254a4 100644 --- a/obp-api/src/test/scala/code/api/v3_1_0/TransactionTest.scala +++ b/obp-api/src/test/scala/code/api/v3_1_0/TransactionTest.scala @@ -26,7 +26,6 @@ TESOBE (http://www.tesobe.com/) package code.api.v3_1_0 import code.api.Constant._ -import com.openbankproject.commons.model.ErrorMessage import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole.CanCreateHistoricalTransaction @@ -42,10 +41,11 @@ import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 import code.api.v3_1_0.OBPAPI3_1_0.Implementations2_2_0 import code.entitlement.Entitlement import com.github.dwickern.macros.NameOf.nameOf -import com.openbankproject.commons.model.AmountOfMoneyJsonV121 +import com.openbankproject.commons.model.{AmountOfMoneyJsonV121, ErrorMessage} import com.openbankproject.commons.util.ApiVersion -import org.scalatest.Tag import net.liftweb.json.Serialization.write +import org.scalatest.Tag +import scala.language.reflectiveCalls class TransactionTest extends V310ServerSetup { @@ -448,7 +448,7 @@ class TransactionTest extends V310ServerSetup { val responseError1 = makePostRequest(request310, write(postJsonCounterparty1)) Then("We should get a 400") - + responseError1.code should equal(400) responseError1.body.toString contains("from object should only contain bank_id and account_id or counterparty_id in the post json body.") should be (true) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala index 3158ed64f..9fa32b652 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala @@ -329,7 +329,7 @@ class AccountTest extends V400ServerSetup { When("We make a request v4.0.0") val request400 = (v4_0_0_Request / "management" / "accounts" / "account-routing-regex-query").POST val postBody = getAccountByRoutingJson.copy(account_routing = AccountRoutingJsonV121("AccountNumber", "123456789-[A-Z]{3}")) - val response400 = makePostRequest(request400, write()) + val response400 = makePostRequest(request400, write(postBody)) Then("We should get a 401") response400.code should equal(401) And("error should be " + UserNotLoggedIn) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AuthenticationTypeValidationTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AuthenticationTypeValidationTest.scala index 8852f2f6b..2088c9d49 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AuthenticationTypeValidationTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AuthenticationTypeValidationTest.scala @@ -1,20 +1,35 @@ package code.api.v4_0_0 import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole +import scala.language.reflectiveCalls import code.api.util.ApiRole._ +import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations2_2_0 +import scala.language.reflectiveCalls import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.APIResponse +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json +import scala.language.reflectiveCalls import net.liftweb.json.JsonAST.JBool +import scala.language.reflectiveCalls import net.liftweb.json.{JArray, JString} +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class AuthenticationTypeValidationTest extends V400ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v4_0_0/ConnectorMethodTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/ConnectorMethodTest.scala index 488b11fb3..e2120abcf 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/ConnectorMethodTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/ConnectorMethodTest.scala @@ -281,7 +281,7 @@ class ConnectorMethodTest extends V400ServerSetup { val future = connectorMethod.getBank(BankId("Hello_bank_id"), None) val result = Await.result(future, Duration.apply(10, TimeUnit.SECONDS)) - result shouldBe a[Full[(Bank, Option[CallContext])]] + result shouldBe a[net.liftweb.common.Box[_]] val Full((bank, _)) = result bank.bankId.value shouldBe "Hello_bank_id" diff --git a/obp-api/src/test/scala/code/api/v4_0_0/ForceErrorValidationTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/ForceErrorValidationTest.scala index b524417ee..6dae1a3f3 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/ForceErrorValidationTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/ForceErrorValidationTest.scala @@ -1,21 +1,37 @@ package code.api.v4_0_0 import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole +import scala.language.reflectiveCalls import code.api.util.ApiRole._ +import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations2_2_0 +import scala.language.reflectiveCalls import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 +import scala.language.reflectiveCalls import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 +import scala.language.reflectiveCalls import code.api.dynamic.endpoint.APIMethodsDynamicEndpoint.ImplementationsDynamicEndpoint +import scala.language.reflectiveCalls import code.api.dynamic.entity.APIMethodsDynamicEntity.ImplementationsDynamicEntity +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.{APIResponse, PropsReset} +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json.{JInt, JString, prettyRender} +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class ForceErrorValidationTest extends V400ServerSetup with PropsReset { diff --git a/obp-api/src/test/scala/code/api/v4_0_0/JsonSchemaValidationTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/JsonSchemaValidationTest.scala index 8ae253ae4..cde7f4bc6 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/JsonSchemaValidationTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/JsonSchemaValidationTest.scala @@ -1,20 +1,35 @@ package code.api.v4_0_0 import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole +import scala.language.reflectiveCalls import code.api.util.ApiRole._ +import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations2_2_0 +import scala.language.reflectiveCalls import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.APIResponse +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json +import scala.language.reflectiveCalls import net.liftweb.json.JsonAST.JBool +import scala.language.reflectiveCalls import net.liftweb.json.{JArray, JString} +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class JsonSchemaValidationTest extends V400ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v4_0_0/TransactionRequestsTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/TransactionRequestsTest.scala index 2988f76c8..645b0ee95 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/TransactionRequestsTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/TransactionRequestsTest.scala @@ -179,8 +179,8 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers { cvv = cardJsonV500.cvv, card_number = cardJsonV500.card_number, name_on_card = cardJsonV500.name_on_card, - expiry_year = (cardJsonV500.expires_date.getYear+1900).toString, - expiry_month = (cardJsonV500.expires_date.getMonth+1).toString + expiry_year = (cardJsonV500.expires_date.toInstant.atZone(java.time.ZoneId.systemDefault()).getYear + 1900).toString, + expiry_month = (cardJsonV500.expires_date.toInstant.atZone(java.time.ZoneId.systemDefault()).getMonthValue).toString ), CounterpartyIdJson(counterpartyCounterparty.counterpartyId), bodyValue, diff --git a/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala index c6aae646c..0bb35ed9f 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala @@ -1,30 +1,54 @@ package code.api.v5_0_0 import code.api.Constant +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.APIUtil.extractErrorMessageCode +import scala.language.reflectiveCalls import code.api.util.ApiRole +import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} +import scala.language.reflectiveCalls import code.api.v2_0_0.BasicAccountJSON +import scala.language.reflectiveCalls import code.api.v2_0_0.OBPAPI2_0_0.Implementations2_0_0 +import scala.language.reflectiveCalls import code.api.v3_0_0.CoreAccountsJsonV300 +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.api.v3_1_0.CreateAccountResponseJsonV310 +import scala.language.reflectiveCalls import code.api.v4_0_0.{AccountsBalancesJsonV400, ModeratedCoreAccountJsonV400} +import scala.language.reflectiveCalls import code.api.v5_0_0.OBPAPI5_0_0.Implementations5_0_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.DefaultUsers +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.enums.AccountRoutingScheme +import scala.language.reflectiveCalls import com.openbankproject.commons.model.{AccountRoutingJsonV121, AmountOfMoneyJsonV121, ErrorMessage} +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls import java.util.UUID +import scala.language.reflectiveCalls import java.util.concurrent.TimeUnit +import scala.language.reflectiveCalls import scala.util.Random +import scala.language.reflectiveCalls class AccountTest extends V500ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v5_0_0/ViewsTests.scala b/obp-api/src/test/scala/code/api/v5_0_0/ViewsTests.scala index c2adc72c6..c99176de7 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/ViewsTests.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/ViewsTests.scala @@ -27,16 +27,26 @@ TESOBE (http://www.tesobe.com/) package code.api.v5_0_0 import code.api.Constant._ +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.v1_2_1.{PermissionJSON, PermissionsJSON} +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.setup.APIResponse +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls import scala.util.Random.nextInt +import scala.language.reflectiveCalls class ViewsTests extends V500ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v5_1_0/ConsentObpTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/ConsentObpTest.scala index 6ce76e53b..dd934c797 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/ConsentObpTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/ConsentObpTest.scala @@ -26,21 +26,37 @@ TESOBE (http://www.tesobe.com/) package code.api.v5_1_0 import code.api.{Constant, RequestHeader} +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import scala.language.reflectiveCalls import code.api.util.ApiRole._ +import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ +import scala.language.reflectiveCalls import code.api.util.{APIUtil, Consent} +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.v3_0_0.{APIMethods300, UserJsonV300} +import scala.language.reflectiveCalls import code.api.v3_1_0.{ConsentJsonV310, PostConsentChallengeJsonV310, PostConsentEntitlementJsonV310, PostConsentViewJsonV310} +import scala.language.reflectiveCalls import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 +import scala.language.reflectiveCalls import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls class ConsentObpTest extends V510ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala index 68789e3d5..3441b5a1e 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala @@ -26,33 +26,60 @@ TESOBE (http://www.tesobe.com/) package code.api.v5_1_0 import code.api.RequestHeader +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON +import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{accountRoutingJsonV121, bankRoutingJsonV121, branchRoutingJsonV141, postCounterpartyLimitV510} +import scala.language.reflectiveCalls import code.api.v5_0_0.ConsentJsonV500 +import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ +import scala.language.reflectiveCalls import code.api.util.ApiRole._ +import scala.language.reflectiveCalls import code.api.util.Consent +import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ +import scala.language.reflectiveCalls import code.api.util.ExampleValue.counterpartyNameExample +import scala.language.reflectiveCalls import code.api.v2_1_0.{CounterpartyIdJson, TransactionRequestBodyCounterpartyJSON} +import scala.language.reflectiveCalls import code.api.v3_0_0.CoreAccountsJsonV300 +import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 +import scala.language.reflectiveCalls import code.api.v3_1_0.PostConsentChallengeJsonV310 +import scala.language.reflectiveCalls import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 +import scala.language.reflectiveCalls import code.api.v4_0_0.{TransactionRequestWithChargeJSON400, UsersJsonV400} +import scala.language.reflectiveCalls import code.api.v5_0_0.ConsentRequestResponseJson +import scala.language.reflectiveCalls import code.api.v5_0_0.OBPAPI5_0_0.Implementations5_0_0 +import scala.language.reflectiveCalls import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 +import scala.language.reflectiveCalls import code.consent.ConsentStatus +import scala.language.reflectiveCalls import code.entitlement.Entitlement +import scala.language.reflectiveCalls import code.setup.PropsReset +import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf +import scala.language.reflectiveCalls import com.openbankproject.commons.model.{AmountOfMoneyJsonV121, ErrorMessage} +import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write +import scala.language.reflectiveCalls import org.scalatest.Tag +import scala.language.reflectiveCalls import scala.language.postfixOps +import scala.language.reflectiveCalls class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ diff --git a/obp-api/src/test/scala/code/api/v6_0_0/CustomerTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/CustomerTest.scala index 7c24dc652..9b14b44c7 100644 --- a/obp-api/src/test/scala/code/api/v6_0_0/CustomerTest.scala +++ b/obp-api/src/test/scala/code/api/v6_0_0/CustomerTest.scala @@ -31,7 +31,7 @@ import code.api.util.ApiRole.{CanCreateCustomer, CanGetCustomersAtOneBank} import code.api.util.ErrorMessages._ import code.api.v3_1_0.PostCustomerNumberJsonV310 import code.api.v6_0_0.OBPAPI6_0_0.Implementations6_0_0 -import code.api.v6_0_0.{CustomerJsonV600, CustomerJSONsV600, CustomerWithAttributesJsonV600, PostCustomerJsonV600} +// Removed imports that shadow local object definitions: CustomerJsonV600, CustomerJSONsV600, CustomerWithAttributesJsonV600, PostCustomerJsonV600 import code.customer.CustomerX import code.entitlement.Entitlement import code.usercustomerlinks.UserCustomerLink diff --git a/obp-api/src/test/scala/code/api/v6_0_0/PasswordResetTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/PasswordResetTest.scala index 90aaeca7e..7fb54f504 100644 --- a/obp-api/src/test/scala/code/api/v6_0_0/PasswordResetTest.scala +++ b/obp-api/src/test/scala/code/api/v6_0_0/PasswordResetTest.scala @@ -31,7 +31,7 @@ import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole._ import com.openbankproject.commons.util.ApiVersion import code.api.util.ErrorMessages._ -import code.api.v6_0_0.APIMethods600 +// Removed import that shadows local object definition: APIMethods600 import code.entitlement.Entitlement import code.model.dataAccess.{AuthUser, ResourceUser} diff --git a/obp-api/src/test/scala/code/connector/ConnectorTest.scala b/obp-api/src/test/scala/code/connector/ConnectorTest.scala index 8765540a7..13e12200e 100644 --- a/obp-api/src/test/scala/code/connector/ConnectorTest.scala +++ b/obp-api/src/test/scala/code/connector/ConnectorTest.scala @@ -1,15 +1,24 @@ package code.connector import code.api.util.{CallContext, OBPQueryParam} +import scala.language.postfixOps import code.api.v5_1_0.V510ServerSetup +import scala.language.postfixOps import code.bankconnectors.Connector +import scala.language.postfixOps import com.github.dwickern.macros.NameOf +import scala.language.postfixOps import com.openbankproject.commons.model.OutboundAdapterCallContext +import scala.language.postfixOps import com.openbankproject.commons.util.ReflectUtils +import scala.language.postfixOps import org.scalatest.{FlatSpec, Matchers, Tag} +import scala.language.postfixOps import scala.collection.immutable.List +import scala.language.postfixOps import scala.reflect.runtime.universe +import scala.language.postfixOps class ConnectorTest extends V510ServerSetup { object ConnectorTestTag extends Tag(NameOf.nameOfType[ConnectorTest]) diff --git a/obp-api/src/test/scala/code/connector/InternalConnectorTest.scala b/obp-api/src/test/scala/code/connector/InternalConnectorTest.scala index a663cf707..792aea78e 100644 --- a/obp-api/src/test/scala/code/connector/InternalConnectorTest.scala +++ b/obp-api/src/test/scala/code/connector/InternalConnectorTest.scala @@ -8,6 +8,7 @@ import org.scalatest.{FlatSpec, Matchers} import scala.concurrent.duration._ import scala.concurrent.Future +import scala.language.postfixOps class InternalConnectorTest extends FlatSpec with Matchers { diff --git a/obp-api/src/test/scala/code/connector/MessageDocTest.scala b/obp-api/src/test/scala/code/connector/MessageDocTest.scala index ab322bd4b..260bf2990 100644 --- a/obp-api/src/test/scala/code/connector/MessageDocTest.scala +++ b/obp-api/src/test/scala/code/connector/MessageDocTest.scala @@ -7,6 +7,7 @@ import code.bankconnectors.LocalMappedConnector import code.setup.DefaultUsers import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.ApiVersion +import scala.language.reflectiveCalls import net.liftweb.json import net.liftweb.json.JValue import org.scalatest.Tag diff --git a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_FrozenTest.scala b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_FrozenTest.scala index e52490a45..352ac126c 100644 --- a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_FrozenTest.scala +++ b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_FrozenTest.scala @@ -12,6 +12,7 @@ import org.scalatest.matchers.{MatchResult, Matcher} import org.scalatest.{BeforeAndAfter, FlatSpec, Matchers, Tag} import scala.reflect.runtime.universe._ +import scala.language.postfixOps /** diff --git a/obp-api/src/test/scala/code/util/FrozenClassUtil.scala b/obp-api/src/test/scala/code/util/FrozenClassUtil.scala index af669f57d..b5a34c656 100644 --- a/obp-api/src/test/scala/code/util/FrozenClassUtil.scala +++ b/obp-api/src/test/scala/code/util/FrozenClassUtil.scala @@ -11,6 +11,7 @@ import net.liftweb.common.Loggable import org.apache.commons.io.IOUtils import scala.reflect.runtime.universe._ +import scala.language.postfixOps /** * this util is for persist metadata of frozen type, those frozen type is versionStatus = "STABLE" related example classes, From c5937d855043085858bc8da83fbeb374146add8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 23 Dec 2025 11:11:26 +0100 Subject: [PATCH 05/48] Revert "feature/Reduce test warnings" This reverts commit 0fcf0b9d457d820c475915d028a6d6cd07021103. --- obp-api/src/test/scala/RunMTLSWebApp.scala | 2 +- obp-api/src/test/scala/RunTLSWebApp.scala | 2 +- obp-api/src/test/scala/code/AppTest.scala | 22 ++++++++------- .../test/scala/code/api/DirectLoginTest.scala | 1 - .../scala/code/api/OBPRestHelperTest.scala | 1 + .../ResourceDocs1_4_0/ResourceDocsTest.scala | 1 - .../ResourceDocs1_4_0/SwaggerDocsTest.scala | 1 - .../code/api/util/JavaWebSignatureTest.scala | 1 - .../scala/code/api/v1_4_0/BranchesTest.scala | 2 -- .../v2_1_0/CreateTransactionTypeTest.scala | 1 - .../code/api/v2_1_0/EntitlementTests.scala | 1 - .../scala/code/api/v2_2_0/API2_2_0Test.scala | 14 ---------- .../code/api/v2_2_0/ExchangeRateTest.scala | 10 ------- .../scala/code/api/v3_0_0/AccountTest.scala | 9 ------- .../scala/code/api/v3_0_0/BranchesTest.scala | 4 --- .../code/api/v3_0_0/CounterpartyTest.scala | 5 ---- .../api/v3_0_0/EntitlementRequestsTest.scala | 10 ------- .../scala/code/api/v3_0_0/FirehoseTest.scala | 11 -------- .../code/api/v3_0_0/GetAdapterInfoTest.scala | 10 ------- .../code/api/v3_0_0/TransactionsTest.scala | 8 ------ .../test/scala/code/api/v3_0_0/UserTest.scala | 15 ----------- .../scala/code/api/v3_0_0/ViewsTests.scala | 15 ----------- .../scala/code/api/v3_0_0/WarehouseTest.scala | 10 ------- .../code/api/v3_0_0/WarehouseTestAsync.scala | 11 -------- .../scala/code/api/v3_1_0/AccountTest.scala | 25 ----------------- .../scala/code/api/v3_1_0/ConsentTest.scala | 16 ----------- .../code/api/v3_1_0/TransactionTest.scala | 8 +++--- .../scala/code/api/v4_0_0/AccountTest.scala | 2 +- .../AuthenticationTypeValidationTest.scala | 15 ----------- .../code/api/v4_0_0/ConnectorMethodTest.scala | 2 +- .../api/v4_0_0/ForceErrorValidationTest.scala | 16 ----------- .../api/v4_0_0/JsonSchemaValidationTest.scala | 15 ----------- .../api/v4_0_0/TransactionRequestsTest.scala | 4 +-- .../scala/code/api/v5_0_0/AccountTest.scala | 24 ----------------- .../scala/code/api/v5_0_0/ViewsTests.scala | 10 ------- .../code/api/v5_1_0/ConsentObpTest.scala | 16 ----------- .../api/v5_1_0/VRPConsentRequestTest.scala | 27 ------------------- .../scala/code/api/v6_0_0/CustomerTest.scala | 2 +- .../code/api/v6_0_0/PasswordResetTest.scala | 2 +- .../scala/code/connector/ConnectorTest.scala | 9 ------- .../connector/InternalConnectorTest.scala | 1 - .../scala/code/connector/MessageDocTest.scala | 1 - .../RestConnector_vMar2019_FrozenTest.scala | 1 - .../scala/code/util/FrozenClassUtil.scala | 1 - 44 files changed, 26 insertions(+), 338 deletions(-) diff --git a/obp-api/src/test/scala/RunMTLSWebApp.scala b/obp-api/src/test/scala/RunMTLSWebApp.scala index 6169fd19b..06381729b 100644 --- a/obp-api/src/test/scala/RunMTLSWebApp.scala +++ b/obp-api/src/test/scala/RunMTLSWebApp.scala @@ -89,7 +89,7 @@ object RunMTLSWebApp extends App with PropsProgrammatically { // RESET HEADER https.addCustomizer(customizer) - val sslContextFactory = new SslContextFactory.Server() + val sslContextFactory = new SslContextFactory() sslContextFactory.setKeyStorePath(this.getClass.getResource("/cert/server.jks").toExternalForm) sslContextFactory.setKeyStorePassword("123456") diff --git a/obp-api/src/test/scala/RunTLSWebApp.scala b/obp-api/src/test/scala/RunTLSWebApp.scala index 718734b5a..dc4f7afff 100644 --- a/obp-api/src/test/scala/RunTLSWebApp.scala +++ b/obp-api/src/test/scala/RunTLSWebApp.scala @@ -89,7 +89,7 @@ object RunTLSWebApp extends App with PropsProgrammatically { // RESET HEADER https.addCustomizer(customizer) - val sslContextFactory = new SslContextFactory.Server() + val sslContextFactory = new SslContextFactory() sslContextFactory.setKeyStorePath(this.getClass.getResource("/cert/server.jks").toExternalForm) sslContextFactory.setKeyStorePassword("123456") diff --git a/obp-api/src/test/scala/code/AppTest.scala b/obp-api/src/test/scala/code/AppTest.scala index 20c50420c..2e8dedba9 100644 --- a/obp-api/src/test/scala/code/AppTest.scala +++ b/obp-api/src/test/scala/code/AppTest.scala @@ -27,29 +27,33 @@ TESOBE (http://www.tesobe.com/) package code import java.io.File +import junit.framework._ +import Assert._ import scala.xml.XML import net.liftweb.util._ import net.liftweb.common._ -import org.scalatest.{FlatSpec, Matchers} object AppTest { + def suite: Test = { + val suite = new TestSuite(classOf[AppTest]) + suite + } + def main(args : Array[String]) { - // Use ScalaTest runner instead - println("Use 'sbt test' or 'mvn test' to run tests") + junit.textui.TestRunner.run(suite) } } /** * Unit test for simple App. */ -class AppTest extends FlatSpec with Matchers { +class AppTest extends TestCase("app") { /** - * Basic functionality test + * Rigourous Tests :-) */ - "App" should "pass basic test" in { - true should be(true) - } + def testOK() = assertTrue(true) + // def testKO() = assertTrue(false); /** * Tests to make sure the project's XML files are well-formed. @@ -57,7 +61,7 @@ class AppTest extends FlatSpec with Matchers { * Finds every *.html and *.xml file in src/main/webapp (and its * subdirectories) and tests to make sure they are well-formed. */ - it should "have well-formed XML files" in { + def testXml() = { var failed: List[File] = Nil def handledXml(file: String) = diff --git a/obp-api/src/test/scala/code/api/DirectLoginTest.scala b/obp-api/src/test/scala/code/api/DirectLoginTest.scala index 9cca2d5e4..2cb1c92c3 100644 --- a/obp-api/src/test/scala/code/api/DirectLoginTest.scala +++ b/obp-api/src/test/scala/code/api/DirectLoginTest.scala @@ -13,7 +13,6 @@ import code.setup.{APIResponse, ServerSetup, TestPasswordConfig} import code.userlocks.UserLocksProvider import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion import net.liftweb.json.JsonAST.{JArray, JField, JObject, JString} import net.liftweb.mapper.By diff --git a/obp-api/src/test/scala/code/api/OBPRestHelperTest.scala b/obp-api/src/test/scala/code/api/OBPRestHelperTest.scala index ddc90c77b..a8bfc06c1 100644 --- a/obp-api/src/test/scala/code/api/OBPRestHelperTest.scala +++ b/obp-api/src/test/scala/code/api/OBPRestHelperTest.scala @@ -1,6 +1,7 @@ package code.api import code.api.util.APIUtil.{ResourceDoc, EmptyBody} +import code.api.OBPRestHelper import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} import org.scalatest.{FlatSpec, Matchers, Tag} diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala index e758d413e..a83097685 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/ResourceDocsTest.scala @@ -9,7 +9,6 @@ import code.api.v1_4_0.JSONFactory1_4_0.ResourceDocsJson import code.setup.{DefaultUsers, PropsReset} import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.{ApiVersion, Functions} -import scala.language.reflectiveCalls import net.liftweb.json import net.liftweb.json.JsonAST._ import net.liftweb.json.{Formats, JString, Serializer, TypeInfo} diff --git a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerDocsTest.scala b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerDocsTest.scala index 2fe764ed5..b96a1acf3 100644 --- a/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerDocsTest.scala +++ b/obp-api/src/test/scala/code/api/ResourceDocs1_4_0/SwaggerDocsTest.scala @@ -5,7 +5,6 @@ import code.api.util.{ApiRole, CustomJsonFormats} import code.setup.{DefaultUsers, PropsReset} import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.{ApiVersion, Functions} -import scala.language.reflectiveCalls import io.swagger.parser.OpenAPIParser import net.liftweb.json import net.liftweb.json.JsonAST._ diff --git a/obp-api/src/test/scala/code/api/util/JavaWebSignatureTest.scala b/obp-api/src/test/scala/code/api/util/JavaWebSignatureTest.scala index 837542615..f62967346 100644 --- a/obp-api/src/test/scala/code/api/util/JavaWebSignatureTest.scala +++ b/obp-api/src/test/scala/code/api/util/JavaWebSignatureTest.scala @@ -11,7 +11,6 @@ import com.github.dwickern.macros.NameOf.nameOf import net.liftweb.common.Full import net.liftweb.util.Helpers._ import org.scalatest.Tag -import scala.language.postfixOps class JavaWebSignatureTest extends V400ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v1_4_0/BranchesTest.scala b/obp-api/src/test/scala/code/api/v1_4_0/BranchesTest.scala index 5eefca75e..e9d6239ca 100644 --- a/obp-api/src/test/scala/code/api/v1_4_0/BranchesTest.scala +++ b/obp-api/src/test/scala/code/api/v1_4_0/BranchesTest.scala @@ -1,6 +1,4 @@ package code.api.v1_4_0 -// Note: This test intentionally uses deprecated model classes (LobbyStringT, DriveUpStringT) -// to maintain backwards compatibility testing. These warnings are expected. import code.api.util.APIUtil.OAuth._ import code.api.util.OBPQueryParam diff --git a/obp-api/src/test/scala/code/api/v2_1_0/CreateTransactionTypeTest.scala b/obp-api/src/test/scala/code/api/v2_1_0/CreateTransactionTypeTest.scala index f2d1c0d06..8a0bedf9b 100644 --- a/obp-api/src/test/scala/code/api/v2_1_0/CreateTransactionTypeTest.scala +++ b/obp-api/src/test/scala/code/api/v2_1_0/CreateTransactionTypeTest.scala @@ -10,7 +10,6 @@ import code.setup.DefaultUsers import code.transaction_types.MappedTransactionType import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model.{AmountOfMoneyJsonV121, ErrorMessage, TransactionTypeId} -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion import net.liftweb.json.Serialization._ import org.scalatest.Tag diff --git a/obp-api/src/test/scala/code/api/v2_1_0/EntitlementTests.scala b/obp-api/src/test/scala/code/api/v2_1_0/EntitlementTests.scala index ecec7ea29..0267f559e 100644 --- a/obp-api/src/test/scala/code/api/v2_1_0/EntitlementTests.scala +++ b/obp-api/src/test/scala/code/api/v2_1_0/EntitlementTests.scala @@ -10,7 +10,6 @@ import code.entitlement.Entitlement import code.setup.DefaultUsers import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import org.scalatest.Tag diff --git a/obp-api/src/test/scala/code/api/v2_2_0/API2_2_0Test.scala b/obp-api/src/test/scala/code/api/v2_2_0/API2_2_0Test.scala index c7b1deebc..34e50d2b3 100644 --- a/obp-api/src/test/scala/code/api/v2_2_0/API2_2_0Test.scala +++ b/obp-api/src/test/scala/code/api/v2_2_0/API2_2_0Test.scala @@ -27,34 +27,20 @@ TESOBE (http://www.tesobe.com/) package code.api.v2_2_0 import code.api.Constant._ -import scala.language.reflectiveCalls import _root_.net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJsonV300 -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.v1_2._ -import scala.language.reflectiveCalls import code.api.v1_2_1.UpdateViewJsonV121 -import scala.language.reflectiveCalls import code.setup.{APIResponse, DefaultUsers} -import scala.language.reflectiveCalls import com.openbankproject.commons.model.CreateViewJson -import scala.language.reflectiveCalls import net.liftweb.util.Helpers._ -import scala.language.reflectiveCalls import org.scalatest._ -import scala.language.reflectiveCalls import code.api.v2_2_0.OBPAPI2_2_0.Implementations2_2_0 -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import scala.util.Random._ -import scala.language.reflectiveCalls class API2_2_0Test extends V220ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v2_2_0/ExchangeRateTest.scala b/obp-api/src/test/scala/code/api/v2_2_0/ExchangeRateTest.scala index aaf37c2a1..2b9896867 100644 --- a/obp-api/src/test/scala/code/api/v2_2_0/ExchangeRateTest.scala +++ b/obp-api/src/test/scala/code/api/v2_2_0/ExchangeRateTest.scala @@ -1,25 +1,15 @@ package code.api.v2_2_0 import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.InvalidISOCurrencyCode -import scala.language.reflectiveCalls import code.consumer.Consumers -import scala.language.reflectiveCalls import code.scope.Scope -import scala.language.reflectiveCalls import code.setup.DefaultUsers -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class ExchangeRateTest extends V220ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/AccountTest.scala index 849bdd74a..d7d759406 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/AccountTest.scala @@ -1,23 +1,14 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole.CanUseAccountFirehoseAtAnyBank -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{AccountFirehoseNotAllowedOnThisInstance, UserHasMissingRoles} -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.setup.APIResponse -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class AccountTest extends V300ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v3_0_0/BranchesTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/BranchesTest.scala index ce4253ca3..579b8e4d8 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/BranchesTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/BranchesTest.scala @@ -1,6 +1,4 @@ package code.api.v3_0_0 -// Note: This test intentionally uses deprecated model classes (LobbyStringT, DriveUpStringT) -// to maintain backwards compatibility testing. These warnings are expected. import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole.CanDeleteBranchAtAnyBank @@ -15,8 +13,6 @@ import code.setup.DefaultUsers import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model._ import org.scalatest.Tag -import scala.language.postfixOps -import scala.language.reflectiveCalls import scala.concurrent.duration._ import scala.concurrent.Await diff --git a/obp-api/src/test/scala/code/api/v3_0_0/CounterpartyTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/CounterpartyTest.scala index ece6cb43a..1dc35fe80 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/CounterpartyTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/CounterpartyTest.scala @@ -1,15 +1,10 @@ package code.api.v3_0_0 import code.api.Constant._ -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class CounterpartyTest extends V300ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v3_0_0/EntitlementRequestsTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/EntitlementRequestsTest.scala index f763fcf75..47417995d 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/EntitlementRequestsTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/EntitlementRequestsTest.scala @@ -1,25 +1,15 @@ package code.api.v3_0_0 import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole.{CanGetEntitlementRequestsAtAnyBank} -import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ -import scala.language.reflectiveCalls import code.api.util.{ApiRole} -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.DefaultUsers -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls /* Note This does not test retrieval from a backend. diff --git a/obp-api/src/test/scala/code/api/v3_0_0/FirehoseTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/FirehoseTest.scala index 1d50e0bbe..45e6b1b36 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/FirehoseTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/FirehoseTest.scala @@ -1,27 +1,16 @@ package code.api.v3_0_0 import code.api.Constant -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole -import scala.language.reflectiveCalls import code.api.util.ApiRole.{CanUseAccountFirehose, CanUseAccountFirehoseAtAnyBank} -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.AccountFirehoseNotAllowedOnThisInstance -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.PropsReset -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class FirehoseTest extends V300ServerSetup with PropsReset{ /** diff --git a/obp-api/src/test/scala/code/api/v3_0_0/GetAdapterInfoTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/GetAdapterInfoTest.scala index a363ee261..c3c7a1e0f 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/GetAdapterInfoTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/GetAdapterInfoTest.scala @@ -26,25 +26,15 @@ TESOBE (http://www.tesobe.com/) package code.api.v3_0_0 import code.api.util.ApiRole.canGetAdapterInfoAtOneBank -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.DefaultUsers -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class GetAdapterInfoTest extends V300ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/TransactionsTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/TransactionsTest.scala index 66e250d6b..487c22e05 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/TransactionsTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/TransactionsTest.scala @@ -1,21 +1,13 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole.CanUseAccountFirehoseAtAnyBank -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{AccountFirehoseNotAllowedOnThisInstance, UserHasMissingRoles} -import scala.language.reflectiveCalls import code.api.util.{APIUtil, ErrorMessages} -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class TransactionsTest extends V300ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/UserTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/UserTest.scala index 4eccea066..bc0ade496 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/UserTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/UserTest.scala @@ -1,35 +1,20 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.{ApiRole, ErrorMessages} -import scala.language.reflectiveCalls import code.api.util.ApiRole.CanGetAnyUser -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.UserHasMissingRoles -import scala.language.reflectiveCalls import code.api.v2_0_0.JSONFactory200.UsersJsonV200 -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.DefaultUsers -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json.JsonAST._ -import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import net.liftweb.util.Helpers.randomString -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class UserTest extends V300ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/ViewsTests.scala b/obp-api/src/test/scala/code/api/v3_0_0/ViewsTests.scala index b567b3aa6..1d6df40d9 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/ViewsTests.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/ViewsTests.scala @@ -27,36 +27,21 @@ TESOBE (http://www.tesobe.com/) package code.api.v3_0_0 import code.api.Constant._ -import scala.language.reflectiveCalls import _root_.net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import code.api.v1_2_1.{APIInfoJSON, PermissionJSON, PermissionsJSON} -import scala.language.reflectiveCalls import code.api.v2_2_0.{ViewJSONV220, ViewsJSONV220} -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.setup.APIResponse -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.{CreateViewJson, UpdateViewJSON} -import scala.language.reflectiveCalls import net.liftweb.util.Helpers._ -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls import scala.util.Random.nextInt -import scala.language.reflectiveCalls class ViewsTests extends V300ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTest.scala b/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTest.scala index 00a364994..3a88f90f2 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTest.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTest.scala @@ -3,25 +3,15 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole.CanSearchWarehouse -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.UserHasMissingRoles -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.setup.{APIResponse, DefaultUsers} -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class WarehouseTest extends V300ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTestAsync.scala b/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTestAsync.scala index 9dfa99f9b..6d0ee3188 100644 --- a/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTestAsync.scala +++ b/obp-api/src/test/scala/code/api/v3_0_0/WarehouseTestAsync.scala @@ -3,28 +3,17 @@ package code.api.v3_0_0 import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole.CanSearchWarehouse -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.UserHasMissingRoles -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.setup.{APIResponse, DefaultUsers} -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls import scala.concurrent.Future -import scala.language.reflectiveCalls class WarehouseTestAsync extends V300ServerSetupAsync with DefaultUsers { /** diff --git a/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala index 94db2bbb5..68c6e0046 100644 --- a/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala @@ -1,56 +1,31 @@ package code.api.v3_1_0 import code.api.Constant -import scala.language.reflectiveCalls import com.openbankproject.commons.model.{AccountRouting, AccountRoutingJsonV121, AmountOfMoneyJsonV121, ErrorMessage, enums} -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.updateAccountRequestJsonV310 -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.APIUtil.extractErrorMessageCode -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} -import scala.language.reflectiveCalls import code.api.util.ApiRole -import scala.language.reflectiveCalls import code.api.v2_0_0.BasicAccountJSON -import scala.language.reflectiveCalls import code.api.v2_2_0.CreateAccountJSONV220 -import scala.language.reflectiveCalls import code.api.v3_0_0.{CoreAccountsJsonV300, ModeratedCoreAccountJsonV300} -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 -import scala.language.reflectiveCalls import code.api.v2_0_0.OBPAPI2_0_0.Implementations2_0_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.model.dataAccess.BankAccountRouting -import scala.language.reflectiveCalls import code.setup.DefaultUsers -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.enums.AccountRoutingScheme -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls import java.util.UUID -import scala.language.reflectiveCalls import java.util.concurrent.TimeUnit -import scala.language.reflectiveCalls import scala.util.Random -import scala.language.reflectiveCalls class AccountTest extends V310ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v3_1_0/ConsentTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/ConsentTest.scala index 1b9db56e1..894c29dbb 100644 --- a/obp-api/src/test/scala/code/api/v3_1_0/ConsentTest.scala +++ b/obp-api/src/test/scala/code/api/v3_1_0/ConsentTest.scala @@ -26,38 +26,22 @@ TESOBE (http://www.tesobe.com/) package code.api.v3_1_0 import code.api.Constant -import scala.language.reflectiveCalls import code.api.RequestHeader -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON -import scala.language.reflectiveCalls import code.api.util.{APIUtil, Consent} -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole._ -import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ -import scala.language.reflectiveCalls import code.api.v3_0_0.{APIMethods300, UserJsonV300} -import scala.language.reflectiveCalls import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls import java.util.Date -import scala.language.reflectiveCalls class ConsentTest extends V310ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v3_1_0/TransactionTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/TransactionTest.scala index 8a5b254a4..f67ddc624 100644 --- a/obp-api/src/test/scala/code/api/v3_1_0/TransactionTest.scala +++ b/obp-api/src/test/scala/code/api/v3_1_0/TransactionTest.scala @@ -26,6 +26,7 @@ TESOBE (http://www.tesobe.com/) package code.api.v3_1_0 import code.api.Constant._ +import com.openbankproject.commons.model.ErrorMessage import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole.CanCreateHistoricalTransaction @@ -41,11 +42,10 @@ import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 import code.api.v3_1_0.OBPAPI3_1_0.Implementations2_2_0 import code.entitlement.Entitlement import com.github.dwickern.macros.NameOf.nameOf -import com.openbankproject.commons.model.{AmountOfMoneyJsonV121, ErrorMessage} +import com.openbankproject.commons.model.AmountOfMoneyJsonV121 import com.openbankproject.commons.util.ApiVersion -import net.liftweb.json.Serialization.write import org.scalatest.Tag -import scala.language.reflectiveCalls +import net.liftweb.json.Serialization.write class TransactionTest extends V310ServerSetup { @@ -448,7 +448,7 @@ class TransactionTest extends V310ServerSetup { val responseError1 = makePostRequest(request310, write(postJsonCounterparty1)) Then("We should get a 400") - + responseError1.code should equal(400) responseError1.body.toString contains("from object should only contain bank_id and account_id or counterparty_id in the post json body.") should be (true) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala index 9fa32b652..3158ed64f 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala @@ -329,7 +329,7 @@ class AccountTest extends V400ServerSetup { When("We make a request v4.0.0") val request400 = (v4_0_0_Request / "management" / "accounts" / "account-routing-regex-query").POST val postBody = getAccountByRoutingJson.copy(account_routing = AccountRoutingJsonV121("AccountNumber", "123456789-[A-Z]{3}")) - val response400 = makePostRequest(request400, write(postBody)) + val response400 = makePostRequest(request400, write()) Then("We should get a 401") response400.code should equal(401) And("error should be " + UserNotLoggedIn) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AuthenticationTypeValidationTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AuthenticationTypeValidationTest.scala index 2088c9d49..8852f2f6b 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AuthenticationTypeValidationTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AuthenticationTypeValidationTest.scala @@ -1,35 +1,20 @@ package code.api.v4_0_0 import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole -import scala.language.reflectiveCalls import code.api.util.ApiRole._ -import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations2_2_0 -import scala.language.reflectiveCalls import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.APIResponse -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json -import scala.language.reflectiveCalls import net.liftweb.json.JsonAST.JBool -import scala.language.reflectiveCalls import net.liftweb.json.{JArray, JString} -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class AuthenticationTypeValidationTest extends V400ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v4_0_0/ConnectorMethodTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/ConnectorMethodTest.scala index e2120abcf..488b11fb3 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/ConnectorMethodTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/ConnectorMethodTest.scala @@ -281,7 +281,7 @@ class ConnectorMethodTest extends V400ServerSetup { val future = connectorMethod.getBank(BankId("Hello_bank_id"), None) val result = Await.result(future, Duration.apply(10, TimeUnit.SECONDS)) - result shouldBe a[net.liftweb.common.Box[_]] + result shouldBe a[Full[(Bank, Option[CallContext])]] val Full((bank, _)) = result bank.bankId.value shouldBe "Hello_bank_id" diff --git a/obp-api/src/test/scala/code/api/v4_0_0/ForceErrorValidationTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/ForceErrorValidationTest.scala index 6dae1a3f3..b524417ee 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/ForceErrorValidationTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/ForceErrorValidationTest.scala @@ -1,37 +1,21 @@ package code.api.v4_0_0 import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole -import scala.language.reflectiveCalls import code.api.util.ApiRole._ -import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations2_2_0 -import scala.language.reflectiveCalls import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 -import scala.language.reflectiveCalls import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 -import scala.language.reflectiveCalls import code.api.dynamic.endpoint.APIMethodsDynamicEndpoint.ImplementationsDynamicEndpoint -import scala.language.reflectiveCalls import code.api.dynamic.entity.APIMethodsDynamicEntity.ImplementationsDynamicEntity -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.{APIResponse, PropsReset} -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json.{JInt, JString, prettyRender} -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class ForceErrorValidationTest extends V400ServerSetup with PropsReset { diff --git a/obp-api/src/test/scala/code/api/v4_0_0/JsonSchemaValidationTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/JsonSchemaValidationTest.scala index cde7f4bc6..8ae253ae4 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/JsonSchemaValidationTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/JsonSchemaValidationTest.scala @@ -1,35 +1,20 @@ package code.api.v4_0_0 import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole -import scala.language.reflectiveCalls import code.api.util.ApiRole._ -import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations2_2_0 -import scala.language.reflectiveCalls import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.APIResponse -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json -import scala.language.reflectiveCalls import net.liftweb.json.JsonAST.JBool -import scala.language.reflectiveCalls import net.liftweb.json.{JArray, JString} -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class JsonSchemaValidationTest extends V400ServerSetup { /** diff --git a/obp-api/src/test/scala/code/api/v4_0_0/TransactionRequestsTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/TransactionRequestsTest.scala index 645b0ee95..2988f76c8 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/TransactionRequestsTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/TransactionRequestsTest.scala @@ -179,8 +179,8 @@ class TransactionRequestsTest extends V400ServerSetup with DefaultUsers { cvv = cardJsonV500.cvv, card_number = cardJsonV500.card_number, name_on_card = cardJsonV500.name_on_card, - expiry_year = (cardJsonV500.expires_date.toInstant.atZone(java.time.ZoneId.systemDefault()).getYear + 1900).toString, - expiry_month = (cardJsonV500.expires_date.toInstant.atZone(java.time.ZoneId.systemDefault()).getMonthValue).toString + expiry_year = (cardJsonV500.expires_date.getYear+1900).toString, + expiry_month = (cardJsonV500.expires_date.getMonth+1).toString ), CounterpartyIdJson(counterpartyCounterparty.counterpartyId), bodyValue, diff --git a/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala index 0bb35ed9f..c6aae646c 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala @@ -1,54 +1,30 @@ package code.api.v5_0_0 import code.api.Constant -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.APIUtil.extractErrorMessageCode -import scala.language.reflectiveCalls import code.api.util.ApiRole -import scala.language.reflectiveCalls import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} -import scala.language.reflectiveCalls import code.api.v2_0_0.BasicAccountJSON -import scala.language.reflectiveCalls import code.api.v2_0_0.OBPAPI2_0_0.Implementations2_0_0 -import scala.language.reflectiveCalls import code.api.v3_0_0.CoreAccountsJsonV300 -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.api.v3_1_0.CreateAccountResponseJsonV310 -import scala.language.reflectiveCalls import code.api.v4_0_0.{AccountsBalancesJsonV400, ModeratedCoreAccountJsonV400} -import scala.language.reflectiveCalls import code.api.v5_0_0.OBPAPI5_0_0.Implementations5_0_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.DefaultUsers -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.enums.AccountRoutingScheme -import scala.language.reflectiveCalls import com.openbankproject.commons.model.{AccountRoutingJsonV121, AmountOfMoneyJsonV121, ErrorMessage} -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls import java.util.UUID -import scala.language.reflectiveCalls import java.util.concurrent.TimeUnit -import scala.language.reflectiveCalls import scala.util.Random -import scala.language.reflectiveCalls class AccountTest extends V500ServerSetup with DefaultUsers { diff --git a/obp-api/src/test/scala/code/api/v5_0_0/ViewsTests.scala b/obp-api/src/test/scala/code/api/v5_0_0/ViewsTests.scala index c99176de7..c2adc72c6 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/ViewsTests.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/ViewsTests.scala @@ -27,26 +27,16 @@ TESOBE (http://www.tesobe.com/) package code.api.v5_0_0 import code.api.Constant._ -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.v1_2_1.{PermissionJSON, PermissionsJSON} -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.setup.APIResponse -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls import scala.util.Random.nextInt -import scala.language.reflectiveCalls class ViewsTests extends V500ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v5_1_0/ConsentObpTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/ConsentObpTest.scala index dd934c797..6ce76e53b 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/ConsentObpTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/ConsentObpTest.scala @@ -26,37 +26,21 @@ TESOBE (http://www.tesobe.com/) package code.api.v5_1_0 import code.api.{Constant, RequestHeader} -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON -import scala.language.reflectiveCalls import code.api.util.ApiRole._ -import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ -import scala.language.reflectiveCalls import code.api.util.{APIUtil, Consent} -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.v3_0_0.{APIMethods300, UserJsonV300} -import scala.language.reflectiveCalls import code.api.v3_1_0.{ConsentJsonV310, PostConsentChallengeJsonV310, PostConsentEntitlementJsonV310, PostConsentViewJsonV310} -import scala.language.reflectiveCalls import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0 -import scala.language.reflectiveCalls import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.ErrorMessage -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls class ConsentObpTest extends V510ServerSetup { diff --git a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala index 3441b5a1e..68789e3d5 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/VRPConsentRequestTest.scala @@ -26,60 +26,33 @@ TESOBE (http://www.tesobe.com/) package code.api.v5_1_0 import code.api.RequestHeader -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON -import scala.language.reflectiveCalls import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{accountRoutingJsonV121, bankRoutingJsonV121, branchRoutingJsonV141, postCounterpartyLimitV510} -import scala.language.reflectiveCalls import code.api.v5_0_0.ConsentJsonV500 -import scala.language.reflectiveCalls import code.api.util.APIUtil.OAuth._ -import scala.language.reflectiveCalls import code.api.util.ApiRole._ -import scala.language.reflectiveCalls import code.api.util.Consent -import scala.language.reflectiveCalls import code.api.util.ErrorMessages._ -import scala.language.reflectiveCalls import code.api.util.ExampleValue.counterpartyNameExample -import scala.language.reflectiveCalls import code.api.v2_1_0.{CounterpartyIdJson, TransactionRequestBodyCounterpartyJSON} -import scala.language.reflectiveCalls import code.api.v3_0_0.CoreAccountsJsonV300 -import scala.language.reflectiveCalls import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0 -import scala.language.reflectiveCalls import code.api.v3_1_0.PostConsentChallengeJsonV310 -import scala.language.reflectiveCalls import code.api.v4_0_0.OBPAPI4_0_0.Implementations4_0_0 -import scala.language.reflectiveCalls import code.api.v4_0_0.{TransactionRequestWithChargeJSON400, UsersJsonV400} -import scala.language.reflectiveCalls import code.api.v5_0_0.ConsentRequestResponseJson -import scala.language.reflectiveCalls import code.api.v5_0_0.OBPAPI5_0_0.Implementations5_0_0 -import scala.language.reflectiveCalls import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 -import scala.language.reflectiveCalls import code.consent.ConsentStatus -import scala.language.reflectiveCalls import code.entitlement.Entitlement -import scala.language.reflectiveCalls import code.setup.PropsReset -import scala.language.reflectiveCalls import com.github.dwickern.macros.NameOf.nameOf -import scala.language.reflectiveCalls import com.openbankproject.commons.model.{AmountOfMoneyJsonV121, ErrorMessage} -import scala.language.reflectiveCalls import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json.Serialization.write -import scala.language.reflectiveCalls import org.scalatest.Tag -import scala.language.reflectiveCalls import scala.language.postfixOps -import scala.language.reflectiveCalls class VRPConsentRequestTest extends V510ServerSetup with PropsReset{ diff --git a/obp-api/src/test/scala/code/api/v6_0_0/CustomerTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/CustomerTest.scala index 9b14b44c7..7c24dc652 100644 --- a/obp-api/src/test/scala/code/api/v6_0_0/CustomerTest.scala +++ b/obp-api/src/test/scala/code/api/v6_0_0/CustomerTest.scala @@ -31,7 +31,7 @@ import code.api.util.ApiRole.{CanCreateCustomer, CanGetCustomersAtOneBank} import code.api.util.ErrorMessages._ import code.api.v3_1_0.PostCustomerNumberJsonV310 import code.api.v6_0_0.OBPAPI6_0_0.Implementations6_0_0 -// Removed imports that shadow local object definitions: CustomerJsonV600, CustomerJSONsV600, CustomerWithAttributesJsonV600, PostCustomerJsonV600 +import code.api.v6_0_0.{CustomerJsonV600, CustomerJSONsV600, CustomerWithAttributesJsonV600, PostCustomerJsonV600} import code.customer.CustomerX import code.entitlement.Entitlement import code.usercustomerlinks.UserCustomerLink diff --git a/obp-api/src/test/scala/code/api/v6_0_0/PasswordResetTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/PasswordResetTest.scala index 7fb54f504..90aaeca7e 100644 --- a/obp-api/src/test/scala/code/api/v6_0_0/PasswordResetTest.scala +++ b/obp-api/src/test/scala/code/api/v6_0_0/PasswordResetTest.scala @@ -31,7 +31,7 @@ import code.api.util.APIUtil.OAuth._ import code.api.util.ApiRole._ import com.openbankproject.commons.util.ApiVersion import code.api.util.ErrorMessages._ -// Removed import that shadows local object definition: APIMethods600 +import code.api.v6_0_0.APIMethods600 import code.entitlement.Entitlement import code.model.dataAccess.{AuthUser, ResourceUser} diff --git a/obp-api/src/test/scala/code/connector/ConnectorTest.scala b/obp-api/src/test/scala/code/connector/ConnectorTest.scala index 13e12200e..8765540a7 100644 --- a/obp-api/src/test/scala/code/connector/ConnectorTest.scala +++ b/obp-api/src/test/scala/code/connector/ConnectorTest.scala @@ -1,24 +1,15 @@ package code.connector import code.api.util.{CallContext, OBPQueryParam} -import scala.language.postfixOps import code.api.v5_1_0.V510ServerSetup -import scala.language.postfixOps import code.bankconnectors.Connector -import scala.language.postfixOps import com.github.dwickern.macros.NameOf -import scala.language.postfixOps import com.openbankproject.commons.model.OutboundAdapterCallContext -import scala.language.postfixOps import com.openbankproject.commons.util.ReflectUtils -import scala.language.postfixOps import org.scalatest.{FlatSpec, Matchers, Tag} -import scala.language.postfixOps import scala.collection.immutable.List -import scala.language.postfixOps import scala.reflect.runtime.universe -import scala.language.postfixOps class ConnectorTest extends V510ServerSetup { object ConnectorTestTag extends Tag(NameOf.nameOfType[ConnectorTest]) diff --git a/obp-api/src/test/scala/code/connector/InternalConnectorTest.scala b/obp-api/src/test/scala/code/connector/InternalConnectorTest.scala index 792aea78e..a663cf707 100644 --- a/obp-api/src/test/scala/code/connector/InternalConnectorTest.scala +++ b/obp-api/src/test/scala/code/connector/InternalConnectorTest.scala @@ -8,7 +8,6 @@ import org.scalatest.{FlatSpec, Matchers} import scala.concurrent.duration._ import scala.concurrent.Future -import scala.language.postfixOps class InternalConnectorTest extends FlatSpec with Matchers { diff --git a/obp-api/src/test/scala/code/connector/MessageDocTest.scala b/obp-api/src/test/scala/code/connector/MessageDocTest.scala index 260bf2990..ab322bd4b 100644 --- a/obp-api/src/test/scala/code/connector/MessageDocTest.scala +++ b/obp-api/src/test/scala/code/connector/MessageDocTest.scala @@ -7,7 +7,6 @@ import code.bankconnectors.LocalMappedConnector import code.setup.DefaultUsers import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.util.ApiVersion -import scala.language.reflectiveCalls import net.liftweb.json import net.liftweb.json.JValue import org.scalatest.Tag diff --git a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_FrozenTest.scala b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_FrozenTest.scala index 352ac126c..e52490a45 100644 --- a/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_FrozenTest.scala +++ b/obp-api/src/test/scala/code/connector/RestConnector_vMar2019_FrozenTest.scala @@ -12,7 +12,6 @@ import org.scalatest.matchers.{MatchResult, Matcher} import org.scalatest.{BeforeAndAfter, FlatSpec, Matchers, Tag} import scala.reflect.runtime.universe._ -import scala.language.postfixOps /** diff --git a/obp-api/src/test/scala/code/util/FrozenClassUtil.scala b/obp-api/src/test/scala/code/util/FrozenClassUtil.scala index b5a34c656..af669f57d 100644 --- a/obp-api/src/test/scala/code/util/FrozenClassUtil.scala +++ b/obp-api/src/test/scala/code/util/FrozenClassUtil.scala @@ -11,7 +11,6 @@ import net.liftweb.common.Loggable import org.apache.commons.io.IOUtils import scala.reflect.runtime.universe._ -import scala.language.postfixOps /** * this util is for persist metadata of frozen type, those frozen type is versionStatus = "STABLE" related example classes, From 6214d3f5d897c941c458f54a9088f454686a2c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 23 Dec 2025 13:36:47 +0100 Subject: [PATCH 06/48] feature/Reduce compiler warnings during compilation --- .../AUOpenBanking/v1_0_0/AccountsApi.scala | 2 ++ .../api/AUOpenBanking/v1_0_0/BankingApi.scala | 1 + .../api/AUOpenBanking/v1_0_0/CommonApi.scala | 2 ++ .../AUOpenBanking/v1_0_0/CustomerApi.scala | 2 ++ .../v1_0_0/DirectDebitsApi.scala | 2 ++ .../AUOpenBanking/v1_0_0/DiscoveryApi.scala | 2 ++ .../api/AUOpenBanking/v1_0_0/PayeesApi.scala | 2 ++ .../AUOpenBanking/v1_0_0/ProductsApi.scala | 1 + .../v1_0_0/ScheduledPaymentsApi.scala | 2 ++ .../v1_0_0/AccountAccessConsentsApi.scala | 1 + .../api/BahrainOBF/v1_0_0/AccountsApi.scala | 1 + .../api/BahrainOBF/v1_0_0/BalancesApi.scala | 1 + .../BahrainOBF/v1_0_0/BeneficiariesApi.scala | 1 + .../BahrainOBF/v1_0_0/DirectDebitsApi.scala | 1 + ...omesticFutureDatedPaymentConsentsApi.scala | 1 + .../DomesticFutureDatedPaymentsApi.scala | 1 + .../v1_0_0/DomesticPaymentsApi.scala | 1 + .../v1_0_0/DomesticPaymentsConsentsApi.scala | 1 + .../v1_0_0/EventNotificationApi.scala | 1 + .../v1_0_0/FilePaymentConsentsApi.scala | 1 + .../BahrainOBF/v1_0_0/FilePaymentsApi.scala | 1 + .../v1_0_0/FutureDatedPaymentsApi.scala | 1 + .../InternationalPaymentConsentsApi.scala | 1 + .../v1_0_0/InternationalPaymentsApi.scala | 1 + .../api/BahrainOBF/v1_0_0/OffersApi.scala | 1 + .../api/BahrainOBF/v1_0_0/PartiesApi.scala | 1 + .../BahrainOBF/v1_0_0/StandingOrdersApi.scala | 1 + .../api/BahrainOBF/v1_0_0/StatementsApi.scala | 1 + .../v1_0_0/SupplementaryAccountInfoApi.scala | 1 + .../BahrainOBF/v1_0_0/TransactionsApi.scala | 1 + .../code/api/MxOF/APIMethods_AtmsApi.scala | 2 ++ .../main/scala/code/api/OBPRestHelper.scala | 2 ++ .../code/api/Polish/v2_1_1_1/AISApi.scala | 1 + .../code/api/Polish/v2_1_1_1/ASApi.scala | 1 + .../code/api/Polish/v2_1_1_1/CAFApi.scala | 1 + .../code/api/Polish/v2_1_1_1/PISApi.scala | 1 + .../ResourceDocs1_4_0/ResourceDocs140.scala | 21 ++++++++++--------- .../ResourceDocsAPIMethods.scala | 8 ++++--- .../scala/code/api/STET/v1_4/AISPApi.scala | 1 + .../scala/code/api/STET/v1_4/CBPIIApi.scala | 1 + .../scala/code/api/STET/v1_4/PISPApi.scala | 1 + .../v3_1_0/AccountAccessApi.scala | 1 + .../UKOpenBanking/v3_1_0/AccountsApi.scala | 1 + .../UKOpenBanking/v3_1_0/BalancesApi.scala | 1 + .../v3_1_0/BeneficiariesApi.scala | 1 + .../v3_1_0/DirectDebitsApi.scala | 1 + .../v3_1_0/DomesticPaymentsApi.scala | 1 + .../v3_1_0/DomesticScheduledPaymentsApi.scala | 1 + .../v3_1_0/DomesticStandingOrdersApi.scala | 1 + .../v3_1_0/FilePaymentsApi.scala | 1 + .../v3_1_0/FundsConfirmationsApi.scala | 1 + .../v3_1_0/InternationalPaymentsApi.scala | 1 + .../InternationalScheduledPaymentsApi.scala | 1 + .../InternationalStandingOrdersApi.scala | 1 + .../api/UKOpenBanking/v3_1_0/OffersApi.scala | 1 + .../api/UKOpenBanking/v3_1_0/PartysApi.scala | 1 + .../UKOpenBanking/v3_1_0/ProductsApi.scala | 1 + .../v3_1_0/ScheduledPaymentsApi.scala | 1 + .../v3_1_0/StandingOrdersApi.scala | 1 + .../UKOpenBanking/v3_1_0/StatementsApi.scala | 1 + .../v3_1_0/TransactionsApi.scala | 1 + .../AccountInformationServiceAISApi.scala | 1 + .../berlin/group/v1_3/CommonServicesApi.scala | 1 + .../ConfirmationOfFundsServicePIISApi.scala | 1 + .../v1_3/PaymentInitiationServicePISApi.scala | 1 + .../berlin/group/v1_3/SigningBasketsApi.scala | 1 + .../main/scala/code/api/util/APIUtil.scala | 2 ++ .../scala/code/api/v1_2_1/OBPAPI1.2.1.scala | 4 +++- .../scala/code/api/v1_3_0/OBPAPI1_3_0.scala | 1 + .../scala/code/api/v1_4_0/APIMethods140.scala | 1 + .../scala/code/api/v1_4_0/OBPAPI1_4_0.scala | 1 + .../scala/code/api/v2_0_0/APIMethods200.scala | 1 + .../scala/code/api/v2_0_0/OBPAPI2_0_0.scala | 1 + .../scala/code/api/v2_1_0/APIMethods210.scala | 1 + .../scala/code/api/v2_1_0/OBPAPI2_1_0.scala | 1 + .../scala/code/api/v2_2_0/APIMethods220.scala | 1 + .../scala/code/api/v2_2_0/OBPAPI2_2_0.scala | 1 + .../scala/code/api/v3_0_0/APIMethods300.scala | 1 + .../scala/code/api/v3_0_0/OBPAPI3_0_0.scala | 1 + .../scala/code/api/v3_1_0/APIMethods310.scala | 1 + .../scala/code/api/v3_1_0/OBPAPI3_1_0.scala | 1 + .../scala/code/api/v4_0_0/APIMethods400.scala | 1 + .../scala/code/api/v4_0_0/OBPAPI4_0_0.scala | 1 + .../scala/code/api/v5_0_0/APIMethods500.scala | 1 + .../scala/code/api/v5_0_0/OBPAPI5_0_0.scala | 1 + .../scala/code/api/v5_1_0/APIMethods510.scala | 1 + .../scala/code/api/v5_1_0/OBPAPI5_1_0.scala | 1 + .../scala/code/api/v6_0_0/APIMethods600.scala | 1 + .../scala/code/api/v6_0_0/OBPAPI6_0_0.scala | 2 ++ 89 files changed, 116 insertions(+), 14 deletions(-) diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/AccountsApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/AccountsApi.scala index 93488b0a9..bca13258f 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/AccountsApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/AccountsApi.scala @@ -1,5 +1,7 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/BankingApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/BankingApi.scala index 21a2776d5..60a9aadf7 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/BankingApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/BankingApi.scala @@ -1,5 +1,6 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil.{defaultBankId, _} import code.api.util.ApiTag._ diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/CommonApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/CommonApi.scala index d89052e67..4b39158e5 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/CommonApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/CommonApi.scala @@ -1,5 +1,7 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/CustomerApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/CustomerApi.scala index 1f829ef99..3e648cab8 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/CustomerApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/CustomerApi.scala @@ -1,5 +1,7 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/DirectDebitsApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/DirectDebitsApi.scala index 4f3a82cac..869e19fe9 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/DirectDebitsApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/DirectDebitsApi.scala @@ -1,5 +1,7 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/DiscoveryApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/DiscoveryApi.scala index ea53f9af5..b434d089c 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/DiscoveryApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/DiscoveryApi.scala @@ -1,5 +1,7 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/PayeesApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/PayeesApi.scala index 1e71822ef..386337d51 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/PayeesApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/PayeesApi.scala @@ -1,5 +1,7 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/ProductsApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/ProductsApi.scala index 12cbfe032..646eed5d3 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/ProductsApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/ProductsApi.scala @@ -1,5 +1,6 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/ScheduledPaymentsApi.scala b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/ScheduledPaymentsApi.scala index 363dbb5b5..289c43eff 100644 --- a/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/ScheduledPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/AUOpenBanking/v1_0_0/ScheduledPaymentsApi.scala @@ -1,5 +1,7 @@ package code.api.AUOpenBanking.v1_0_0 +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/AccountAccessConsentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/AccountAccessConsentsApi.scala index 6a5275caa..0bfaa7526 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/AccountAccessConsentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/AccountAccessConsentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/AccountsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/AccountsApi.scala index fbbe36828..aca6e29c0 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/AccountsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/AccountsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/BalancesApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/BalancesApi.scala index f348050e2..6dfe3ce89 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/BalancesApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/BalancesApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/BeneficiariesApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/BeneficiariesApi.scala index 4a58944c5..c10d058b4 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/BeneficiariesApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/BeneficiariesApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DirectDebitsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DirectDebitsApi.scala index c956e1af7..99e23cf40 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DirectDebitsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DirectDebitsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticFutureDatedPaymentConsentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticFutureDatedPaymentConsentsApi.scala index 5f59bfe66..b52926915 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticFutureDatedPaymentConsentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticFutureDatedPaymentConsentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticFutureDatedPaymentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticFutureDatedPaymentsApi.scala index 157df8b11..97340d0a3 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticFutureDatedPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticFutureDatedPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticPaymentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticPaymentsApi.scala index 9e0c1a894..3491ae02d 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticPaymentsConsentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticPaymentsConsentsApi.scala index 4db4c0b41..8b03e9e4a 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticPaymentsConsentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/DomesticPaymentsConsentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/EventNotificationApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/EventNotificationApi.scala index 2d40272d5..244088bda 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/EventNotificationApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/EventNotificationApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FilePaymentConsentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FilePaymentConsentsApi.scala index 965d1f09b..822677061 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FilePaymentConsentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FilePaymentConsentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FilePaymentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FilePaymentsApi.scala index 0dbd97d5b..166234039 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FilePaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FilePaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FutureDatedPaymentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FutureDatedPaymentsApi.scala index 1a3353ac2..bd2958efb 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FutureDatedPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/FutureDatedPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/InternationalPaymentConsentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/InternationalPaymentConsentsApi.scala index 684a13c20..f5c237689 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/InternationalPaymentConsentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/InternationalPaymentConsentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/InternationalPaymentsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/InternationalPaymentsApi.scala index ef052b261..a566e2bb1 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/InternationalPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/InternationalPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/OffersApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/OffersApi.scala index 107fec5c1..1fb6ba9ee 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/OffersApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/OffersApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/PartiesApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/PartiesApi.scala index 847fec053..1e5ab3666 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/PartiesApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/PartiesApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/StandingOrdersApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/StandingOrdersApi.scala index 2d9b227e2..d3722d395 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/StandingOrdersApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/StandingOrdersApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/StatementsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/StatementsApi.scala index d17d2afa0..aaa6102cd 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/StatementsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/StatementsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/SupplementaryAccountInfoApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/SupplementaryAccountInfoApi.scala index 0a26024ca..d4dec4f4d 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/SupplementaryAccountInfoApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/SupplementaryAccountInfoApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/TransactionsApi.scala b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/TransactionsApi.scala index 8528cd690..12c2cf3d3 100644 --- a/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/TransactionsApi.scala +++ b/obp-api/src/main/scala/code/api/BahrainOBF/v1_0_0/TransactionsApi.scala @@ -1,5 +1,6 @@ package code.api.BahrainOBF.v1_0_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/MxOF/APIMethods_AtmsApi.scala b/obp-api/src/main/scala/code/api/MxOF/APIMethods_AtmsApi.scala index 6ede06c1e..65089ecf7 100644 --- a/obp-api/src/main/scala/code/api/MxOF/APIMethods_AtmsApi.scala +++ b/obp-api/src/main/scala/code/api/MxOF/APIMethods_AtmsApi.scala @@ -1,5 +1,7 @@ package code.api.MxOF +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.Constant import code.api.MxOF.JSONFactory_MXOF_0_0_1.createGetAtmsResponse import code.api.util.APIUtil._ diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index ea6adbdbb..78dc3bde3 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -27,6 +27,8 @@ TESOBE (http://www.tesobe.com/) package code.api +import scala.language.reflectiveCalls +import scala.language.implicitConversions import code.api.Constant._ import code.api.OAuthHandshake._ import code.api.util.APIUtil._ diff --git a/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/AISApi.scala b/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/AISApi.scala index 1c4b6fa18..82b4965c0 100644 --- a/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/AISApi.scala +++ b/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/AISApi.scala @@ -1,5 +1,6 @@ package code.api.Polish.v2_1_1_1 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/ASApi.scala b/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/ASApi.scala index 40a4131f2..51c0488e0 100644 --- a/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/ASApi.scala +++ b/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/ASApi.scala @@ -1,5 +1,6 @@ package code.api.Polish.v2_1_1_1 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/CAFApi.scala b/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/CAFApi.scala index ac460d996..a23d8151a 100644 --- a/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/CAFApi.scala +++ b/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/CAFApi.scala @@ -1,5 +1,6 @@ package code.api.Polish.v2_1_1_1 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/PISApi.scala b/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/PISApi.scala index bc343808a..079d30030 100644 --- a/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/PISApi.scala +++ b/obp-api/src/main/scala/code/api/Polish/v2_1_1_1/PISApi.scala @@ -1,5 +1,6 @@ package code.api.Polish.v2_1_1_1 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala index 3845c33ea..2a43e1d6c 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala @@ -1,5 +1,6 @@ package code.api.ResourceDocs1_4_0 +import scala.language.reflectiveCalls import code.api.Constant.HostName import code.api.OBPRestHelper import code.api.cache.Caching @@ -16,7 +17,7 @@ import net.liftweb.http.{GetRequest, InMemoryResponse, PlainTextResponse, Req, S object ResourceDocs140 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version = ApiVersion.v1_4_0 // "1.4.0" // We match other api versions so API explorer can easily use the path. val versionStatus = ApiVersionStatus.STABLE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, @@ -31,7 +32,7 @@ object ResourceDocs140 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs200 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version = ApiVersion.v2_0_0 // "2.0.0" // We match other api versions so API explorer can easily use the path. val versionStatus = ApiVersionStatus.STABLE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, @@ -46,7 +47,7 @@ object ResourceDocs200 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs210 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version: ApiVersion = ApiVersion.v2_1_0 // "2.1.0" // We match other api versions so API explorer can easily use the path. val versionStatus = ApiVersionStatus.STABLE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, @@ -60,7 +61,7 @@ object ResourceDocs210 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs220 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version: ApiVersion = ApiVersion.v2_2_0 // "2.2.0" // We match other api versions so API explorer can easily use the path. val versionStatus = ApiVersionStatus.STABLE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, @@ -74,7 +75,7 @@ object ResourceDocs220 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version : ApiVersion = ApiVersion.v3_0_0 // = "3.0.0" // We match other api versions so API explorer can easily use the path. val versionStatus = ApiVersionStatus.STABLE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, @@ -87,7 +88,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs310 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version: ApiVersion = ApiVersion.v3_1_0 // = "3.0.0" // We match other api versions so API explorer can easily use the path. val versionStatus = ApiVersionStatus.STABLE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObp, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, @@ -102,7 +103,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs400 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version: ApiVersion = ApiVersion.v4_0_0 // = "4.0.0" // We match other api versions so API explorer can easily use the path. val versionStatus = ApiVersionStatus.STABLE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObpV400, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, @@ -117,7 +118,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs500 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version: ApiVersion = ApiVersion.v5_0_0 val versionStatus = ApiVersionStatus.STABLE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObpV400, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, @@ -132,7 +133,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs510 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version: ApiVersion = ApiVersion.v5_1_0 val versionStatus = ApiVersionStatus.BLEEDING_EDGE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObpV400, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getBankLevelDynamicResourceDocsObp, @@ -148,7 +149,7 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md object ResourceDocs600 extends OBPRestHelper with ResourceDocsAPIMethods with MdcLoggable { val version: ApiVersion = ApiVersion.v6_0_0 val versionStatus = ApiVersionStatus.BLEEDING_EDGE.toString - val routes = List( + val routes: Seq[OBPEndpoint] = List( ImplementationsResourceDocs.getResourceDocsObpV400, ImplementationsResourceDocs.getResourceDocsSwagger, ImplementationsResourceDocs.getResourceDocsOpenAPI31, diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 9d5c894b3..27d3a22e0 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -1,6 +1,7 @@ package code.api.ResourceDocs1_4_0 -import code.api.Constant.{GET_DYNAMIC_RESOURCE_DOCS_TTL, GET_STATIC_RESOURCE_DOCS_TTL, PARAM_LOCALE, HostName} +import scala.language.reflectiveCalls +import code.api.Constant.{GET_DYNAMIC_RESOURCE_DOCS_TTL, GET_STATIC_RESOURCE_DOCS_TTL, HostName, PARAM_LOCALE} import code.api.OBPRestHelper import code.api.cache.Caching import code.api.util.APIUtil._ @@ -39,6 +40,7 @@ import net.liftweb.json.JsonAST.{JField, JString, JValue} import net.liftweb.json._ import java.util.concurrent.ConcurrentHashMap +import scala.collection.immutable import scala.collection.immutable.{List, Nil} import scala.concurrent.Future @@ -117,7 +119,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth logger.debug(s"getResourceDocsList says requestedApiVersion is $requestedApiVersion") - val resourceDocs = requestedApiVersion match { + val resourceDocs: ArrayBuffer[ResourceDoc] = requestedApiVersion match { case ApiVersion.v6_0_0 => OBPAPI6_0_0.allResourceDocs case ApiVersion.v5_1_0 => OBPAPI5_1_0.allResourceDocs case ApiVersion.v5_0_0 => OBPAPI5_0_0.allResourceDocs @@ -138,7 +140,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth logger.debug(s"There are ${resourceDocs.length} resource docs available to $requestedApiVersion") - val versionRoutes = requestedApiVersion match { + val versionRoutes: immutable.Seq[OBPEndpoint] = requestedApiVersion match { case ApiVersion.v6_0_0 => OBPAPI6_0_0.routes case ApiVersion.v5_1_0 => OBPAPI5_1_0.routes case ApiVersion.v5_0_0 => OBPAPI5_0_0.routes diff --git a/obp-api/src/main/scala/code/api/STET/v1_4/AISPApi.scala b/obp-api/src/main/scala/code/api/STET/v1_4/AISPApi.scala index a2175d0b9..7eeb835ab 100644 --- a/obp-api/src/main/scala/code/api/STET/v1_4/AISPApi.scala +++ b/obp-api/src/main/scala/code/api/STET/v1_4/AISPApi.scala @@ -1,5 +1,6 @@ package code.api.STET.v1_4 +import scala.language.implicitConversions import code.api.APIFailureNewStyle import code.api.STET.v1_4.JSONFactory_STET_1_4._ import code.api.berlin.group.v1_3.JvalueCaseClass diff --git a/obp-api/src/main/scala/code/api/STET/v1_4/CBPIIApi.scala b/obp-api/src/main/scala/code/api/STET/v1_4/CBPIIApi.scala index bd249bbc1..7c64f54ee 100644 --- a/obp-api/src/main/scala/code/api/STET/v1_4/CBPIIApi.scala +++ b/obp-api/src/main/scala/code/api/STET/v1_4/CBPIIApi.scala @@ -1,5 +1,6 @@ package code.api.STET.v1_4 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/STET/v1_4/PISPApi.scala b/obp-api/src/main/scala/code/api/STET/v1_4/PISPApi.scala index 1a3b504bc..8dde01b43 100644 --- a/obp-api/src/main/scala/code/api/STET/v1_4/PISPApi.scala +++ b/obp-api/src/main/scala/code/api/STET/v1_4/PISPApi.scala @@ -1,5 +1,6 @@ package code.api.STET.v1_4 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/AccountAccessApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/AccountAccessApi.scala index 1b99efeb1..2221a08cb 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/AccountAccessApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/AccountAccessApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.Constant import code.api.UKOpenBanking.v3_1_0.JSONFactory_UKOpenBanking_310.ConsentPostBodyUKV310 import code.api.berlin.group.v1_3.JvalueCaseClass diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/AccountsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/AccountsApi.scala index d85e236ee..af76a559f 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/AccountsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/AccountsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.Constant import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/BalancesApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/BalancesApi.scala index afa47da0d..7f5196a24 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/BalancesApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/BalancesApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.Constant import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/BeneficiariesApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/BeneficiariesApi.scala index 8b2a9202f..a8bdf4a6f 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/BeneficiariesApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/BeneficiariesApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DirectDebitsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DirectDebitsApi.scala index 0fa62f861..691d74797 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DirectDebitsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DirectDebitsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticPaymentsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticPaymentsApi.scala index a3eb5c672..26c9f7441 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticScheduledPaymentsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticScheduledPaymentsApi.scala index 235d2e139..8a9c8fdf4 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticScheduledPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticScheduledPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticStandingOrdersApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticStandingOrdersApi.scala index ee21f7fc4..9af02bff7 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticStandingOrdersApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/DomesticStandingOrdersApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/FilePaymentsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/FilePaymentsApi.scala index 216d31cc7..ff17971f8 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/FilePaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/FilePaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/FundsConfirmationsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/FundsConfirmationsApi.scala index 3dce3f6b8..61d110fb4 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/FundsConfirmationsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/FundsConfirmationsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalPaymentsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalPaymentsApi.scala index d5206696d..4902fc0c8 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalScheduledPaymentsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalScheduledPaymentsApi.scala index e7f2ea6b0..7dd09f027 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalScheduledPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalScheduledPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalStandingOrdersApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalStandingOrdersApi.scala index bb6b4f77f..f35323886 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalStandingOrdersApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/InternationalStandingOrdersApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/OffersApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/OffersApi.scala index eb7cfc90b..953810052 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/OffersApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/OffersApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/PartysApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/PartysApi.scala index cc066d556..4a8c43e58 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/PartysApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/PartysApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/ProductsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/ProductsApi.scala index a623afaa1..4542578c9 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/ProductsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/ProductsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/ScheduledPaymentsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/ScheduledPaymentsApi.scala index 163759ba7..826fd9d8d 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/ScheduledPaymentsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/ScheduledPaymentsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/StandingOrdersApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/StandingOrdersApi.scala index 48772074d..f44769525 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/StandingOrdersApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/StandingOrdersApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/StatementsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/StatementsApi.scala index 69a893f0d..66be44423 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/StatementsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/StatementsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil._ import code.api.util.ApiTag diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/TransactionsApi.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/TransactionsApi.scala index 5a5718106..3b1f0e8b1 100644 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/TransactionsApi.scala +++ b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/TransactionsApi.scala @@ -1,5 +1,6 @@ package code.api.UKOpenBanking.v3_1_0 +import scala.language.implicitConversions import code.api.berlin.group.v1_3.JvalueCaseClass import code.api.util.APIUtil.{defaultBankId, _} import code.api.util.ApiTag._ diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala index d3684b268..df55fbfd0 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApi.scala @@ -1,5 +1,6 @@ package code.api.builder.AccountInformationServiceAISApi +import scala.language.implicitConversions import code.api.APIFailureNewStyle import code.api.Constant.{SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID, SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID, SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID} import code.api.berlin.group.ConstantsBG diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/CommonServicesApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/CommonServicesApi.scala index 34b0f54f6..6a40112e9 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/CommonServicesApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/CommonServicesApi.scala @@ -1,5 +1,6 @@ package code.api.builder.CommonServicesApi +import scala.language.implicitConversions import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.{JvalueCaseClass, OBP_BERLIN_GROUP_1_3} import code.api.builder.AccountInformationServiceAISApi.APIMethods_AccountInformationServiceAISApi diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/ConfirmationOfFundsServicePIISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/ConfirmationOfFundsServicePIISApi.scala index 7e5108aa7..adde2f1fb 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/ConfirmationOfFundsServicePIISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/ConfirmationOfFundsServicePIISApi.scala @@ -1,5 +1,6 @@ package code.api.builder.ConfirmationOfFundsServicePIISApi +import scala.language.implicitConversions import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3._ import code.api.berlin.group.v1_3.{JvalueCaseClass, OBP_BERLIN_GROUP_1_3} diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala index 0d39f7502..ac2618326 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala @@ -1,5 +1,6 @@ package code.api.builder.PaymentInitiationServicePISApi +import scala.language.implicitConversions import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{CancelPaymentResponseJson, CancelPaymentResponseLinks, LinkHrefJson, UpdatePaymentPsuDataJson, checkAuthorisationConfirmation, checkSelectPsuAuthenticationMethod, checkTransactionAuthorisation, checkUpdatePsuAuthentication, createCancellationTransactionRequestJson} import code.api.berlin.group.v1_3.model.TransactionStatus.mapTransactionStatus diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala index 8b1c05891..664bcee8e 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/SigningBasketsApi.scala @@ -1,5 +1,6 @@ package code.api.builder.SigningBasketsApi +import scala.language.implicitConversions import code.api.berlin.group.ConstantsBG import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{PostSigningBasketJsonV13, UpdatePaymentPsuDataJson, createSigningBasketResponseJson, createStartSigningBasketAuthorisationJson, getSigningBasketResponseJson, getSigningBasketStatusResponseJson} import code.api.berlin.group.v1_3.{JSONFactory_BERLIN_GROUP_1_3, JvalueCaseClass} diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index d6fb5dbb4..684290acb 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -26,6 +26,8 @@ TESOBE (http://www.tesobe.com/) */ package code.api.util + +import scala.language.implicitConversions import bootstrap.liftweb.CustomDBVendor import code.accountholders.AccountHolders import code.api.Constant._ diff --git a/obp-api/src/main/scala/code/api/v1_2_1/OBPAPI1.2.1.scala b/obp-api/src/main/scala/code/api/v1_2_1/OBPAPI1.2.1.scala index 5c550e036..113d684b1 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/OBPAPI1.2.1.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/OBPAPI1.2.1.scala @@ -26,6 +26,8 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v1_2_1 +import scala.language.implicitConversions +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import com.openbankproject.commons.util.{ApiVersion,ApiVersionStatus} @@ -40,7 +42,7 @@ object OBPAPI1_2_1 extends OBPRestHelper with APIMethods121 with MdcLoggable wit val version : ApiVersion = ApiVersion.v1_2_1 // "1.2.1" val versionStatus = ApiVersionStatus.DEPRECATED.toString - lazy val endpointsOf1_2_1 = List( + lazy val endpointsOf1_2_1: Seq[OBPEndpoint] = List( Implementations1_2_1.root, Implementations1_2_1.getBanks, Implementations1_2_1.bankById, diff --git a/obp-api/src/main/scala/code/api/v1_3_0/OBPAPI1_3_0.scala b/obp-api/src/main/scala/code/api/v1_3_0/OBPAPI1_3_0.scala index 7dccdf33d..d5b6ce050 100644 --- a/obp-api/src/main/scala/code/api/v1_3_0/OBPAPI1_3_0.scala +++ b/obp-api/src/main/scala/code/api/v1_3_0/OBPAPI1_3_0.scala @@ -1,5 +1,6 @@ package code.api.v1_3_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import com.openbankproject.commons.util.{ApiVersion,ApiVersionStatus} diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index a8ac7072c..31d7fe239 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -1,5 +1,6 @@ package code.api.v1_4_0 +import scala.language.reflectiveCalls import code.api.Constant._ import code.api.util.ApiRole._ import code.api.util.ApiTag._ diff --git a/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala index 57d6d2180..86c282757 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/OBPAPI1_4_0.scala @@ -1,5 +1,6 @@ package code.api.v1_4_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import com.openbankproject.commons.util.{ApiVersion,ApiVersionStatus} diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index b496bee72..2ed09e34a 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -1,5 +1,6 @@ package code.api.v2_0_0 +import scala.language.reflectiveCalls import code.TransactionTypes.TransactionType import code.api.APIFailureNewStyle import code.api.Constant._ diff --git a/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala b/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala index 6e037559c..c642e154a 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/OBPAPI2_0_0.scala @@ -26,6 +26,7 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v2_0_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import com.openbankproject.commons.util.{ApiVersion,ApiVersionStatus} diff --git a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala index 5280a9267..4b98fa835 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala @@ -1,5 +1,6 @@ package code.api.v2_1_0 +import scala.language.reflectiveCalls import code.TransactionTypes.TransactionType import code.api.Constant.CAN_SEE_TRANSACTION_REQUESTS import code.api.util.ApiTag._ diff --git a/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala b/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala index e796bbee5..eaab7b2d0 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/OBPAPI2_1_0.scala @@ -26,6 +26,7 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v2_1_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import code.api.util.{APIUtil, VersionedOBPApis} diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index e6af9eba3..80ff18aae 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -1,5 +1,6 @@ package code.api.v2_2_0 +import scala.language.reflectiveCalls import code.api.Constant._ import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil._ diff --git a/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala b/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala index d618322c2..eef388578 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/OBPAPI2_2_0.scala @@ -1,6 +1,7 @@ package code.api.v2_2_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import code.api.util.{APIUtil, VersionedOBPApis} diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index 400da0234..7c0be82d2 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -1,5 +1,6 @@ package code.api.v3_0_0 +import scala.language.reflectiveCalls import code.accountattribute.AccountAttributeX import code.api.Constant._ import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON diff --git a/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala b/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala index fad91faae..d8bd8f86c 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/OBPAPI3_0_0.scala @@ -26,6 +26,7 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v3_0_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import com.openbankproject.commons.util.{ApiVersion,ApiVersionStatus} diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index b88d88b49..cbec5f5b3 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1,5 +1,6 @@ package code.api.v3_1_0 +import scala.language.reflectiveCalls import code.api.Constant import code.api.Constant._ import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ diff --git a/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala b/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala index b581773be..fe1b43249 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/OBPAPI3_1_0.scala @@ -26,6 +26,7 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v3_1_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import com.openbankproject.commons.util.{ApiVersion,ApiVersionStatus} diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 78228ef5f..7453131ba 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -1,5 +1,6 @@ package code.api.v4_0_0 +import scala.language.reflectiveCalls import code.DynamicData.DynamicData import code.DynamicEndpoint.DynamicEndpointSwagger import code.accountattribute.AccountAttributeX diff --git a/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala b/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala index 0d8c671fa..089a7bc14 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/OBPAPI4_0_0.scala @@ -26,6 +26,7 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v4_0_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import code.api.util.VersionedOBPApis diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 129d217c3..f7f83ee98 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -1,5 +1,6 @@ package code.api.v5_0_0 +import scala.language.reflectiveCalls import code.accountattribute.AccountAttributeX import code.api.Constant._ import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ diff --git a/obp-api/src/main/scala/code/api/v5_0_0/OBPAPI5_0_0.scala b/obp-api/src/main/scala/code/api/v5_0_0/OBPAPI5_0_0.scala index 24110ea73..ac3528d8d 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/OBPAPI5_0_0.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/OBPAPI5_0_0.scala @@ -26,6 +26,7 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v5_0_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import code.api.util.{APIUtil, VersionedOBPApis} diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 6b5c0e479..3029949c2 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -1,6 +1,7 @@ package code.api.v5_1_0 +import scala.language.reflectiveCalls import code.api.Constant import code.api.Constant._ import code.api.OAuth2Login.{Keycloak, OBPOIDC} diff --git a/obp-api/src/main/scala/code/api/v5_1_0/OBPAPI5_1_0.scala b/obp-api/src/main/scala/code/api/v5_1_0/OBPAPI5_1_0.scala index 804e2eb5e..3a7f94e39 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/OBPAPI5_1_0.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/OBPAPI5_1_0.scala @@ -26,6 +26,7 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v5_1_0 +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import code.api.util.{APIUtil, VersionedOBPApis} diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index d76163578..881c93120 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -1,5 +1,6 @@ package code.api.v6_0_0 +import scala.language.reflectiveCalls import code.accountattribute.AccountAttributeX import code.api.Constant import code.api.{DirectLogin, ObpApiFailure} diff --git a/obp-api/src/main/scala/code/api/v6_0_0/OBPAPI6_0_0.scala b/obp-api/src/main/scala/code/api/v6_0_0/OBPAPI6_0_0.scala index 6b1868e7d..b6a30baf5 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/OBPAPI6_0_0.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/OBPAPI6_0_0.scala @@ -26,6 +26,8 @@ TESOBE (http://www.tesobe.com/) */ package code.api.v6_0_0 + +import scala.language.reflectiveCalls import code.api.OBPRestHelper import code.api.util.APIUtil.{OBPEndpoint, getAllowedEndpoints} import code.api.util.VersionedOBPApis From 5cbe019e5a77f287f41e1130704d320ff2527c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 23 Dec 2025 15:39:08 +0100 Subject: [PATCH 07/48] feature/Reduce compiler warnings during compilation 2 --- .../ResourceDocsAPIMethods.scala | 4 ++-- .../SwaggerDefinitionsJSON.scala | 1 + .../SwaggerJSONFactory.scala | 8 ++++---- .../helper/DynamicCompileEndpoint.scala | 3 ++- .../helper/DynamicEndpointHelper.scala | 3 ++- .../main/scala/code/api/util/APIUtil.scala | 11 +++++----- .../main/scala/code/api/util/NewStyle.scala | 8 ++++---- .../scala/code/api/v1_2_1/APIMethods121.scala | 4 ++-- .../scala/code/api/v1_3_0/APIMethods130.scala | 2 +- .../scala/code/api/v1_4_0/APIMethods140.scala | 2 +- .../code/api/v1_4_0/JSONFactory1_4_0.scala | 2 +- .../scala/code/api/v2_0_0/APIMethods200.scala | 2 +- .../scala/code/api/v2_1_0/APIMethods210.scala | 2 +- .../scala/code/api/v2_2_0/APIMethods220.scala | 8 ++++---- .../scala/code/api/v3_0_0/APIMethods300.scala | 4 ++-- .../scala/code/api/v3_1_0/APIMethods310.scala | 2 +- .../code/api/v3_1_0/JSONFactory3.1.0.scala | 2 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 20 +++++++++---------- .../scala/code/api/v5_0_0/APIMethods500.scala | 6 +++--- .../scala/code/api/v5_1_0/APIMethods510.scala | 4 ++-- .../scala/code/api/v6_0_0/APIMethods600.scala | 8 ++++---- .../scala/code/api/v7_0_0/Http4s700.scala | 2 +- .../MappedAuthTypeValidationProvider.scala | 2 +- .../scala/code/bankconnectors/Connector.scala | 7 ++++--- .../bankconnectors/InternalConnector.scala | 8 ++++---- .../LocalMappedConnectorInternal.scala | 2 +- .../akka/actor/AkkaConnectorActorInit.scala | 2 +- .../rest/RestConnector_vMar2019.scala | 1 + .../MappedConnectorMethodProvider.scala | 4 ++-- .../MapppedDynamicEndpointProvider.scala | 2 +- .../MappedDynamicMessageDocProvider.scala | 2 +- .../MappedDynamicResourceDocProvider.scala | 2 +- obp-api/src/main/scala/code/fx/fx.scala | 2 +- .../scala/code/management/ImporterAPI.scala | 2 +- .../counterparties/MapperCounterparties.scala | 2 +- .../scala/code/metrics/ConnectorMetrics.scala | 2 +- .../scala/code/metrics/MappedMetrics.scala | 8 ++++---- .../code/model/ModeratedBankingData.scala | 6 ++++++ obp-api/src/main/scala/code/model/OAuth.scala | 4 ++-- obp-api/src/main/scala/code/model/View.scala | 2 ++ .../code/model/dataAccess/AuthUser.scala | 2 +- .../code/model/dataAccess/ResourceUser.scala | 2 +- .../src/main/scala/code/model/package.scala | 2 ++ .../src/main/scala/code/obp/grpc/Client.scala | 1 + .../code/obp/grpc/HelloWorldServer.scala | 2 ++ .../src/main/scala/code/search/search.scala | 4 ++-- .../scala/code/snippet/GetHtmlFromUrl.scala | 2 +- .../src/main/scala/code/snippet/WebUI.scala | 2 +- .../main/scala/code/util/AkkaHttpClient.scala | 2 +- obp-api/src/main/scala/code/util/Helper.scala | 6 +++--- .../MappedJsonSchemaValidationProvider.scala | 2 +- .../main/scala/code/views/MapperViews.scala | 4 ++-- .../webuiprops/MappedWebUiPropsProvider.scala | 2 +- 53 files changed, 110 insertions(+), 91 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 3abd43323..d83e02506 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -468,7 +468,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case true => authenticatedAccess(cc) // If set resource_docs_requires_role=true, we need check the authentication } _ <- resourceDocsRequireRole match { - case false => Future() + case false => Future(()) case true => // If set resource_docs_requires_role=true, we need check the roles as well NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + canReadResourceDoc.toString)("", u.map(_.userId).getOrElse(""), ApiRole.canReadResourceDoc :: Nil, cc.callContext) } @@ -592,7 +592,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } (_, callContext) <- NewStyle.function.getBank(BankId(bankId), Option(cc)) _ <- resourceDocsRequireRole match { - case false => Future() + case false => Future(()) case true => // If set resource_docs_requires_role=true, we need check the the roles as well NewStyle.function.hasAtLeastOneEntitlement(failMsg = UserHasMissingRoles + ApiRole.canReadDynamicResourceDocsAtOneBank.toString)( bankId, u.map(_.userId).getOrElse(""), ApiRole.canReadDynamicResourceDocsAtOneBank::Nil, cc.callContext diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index d6e9149ea..a1e5223c0 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -1,5 +1,6 @@ package code.api.ResourceDocs1_4_0 +import scala.language.implicitConversions import code.api.Constant import code.api.Constant._ import code.api.UKOpenBanking.v2_0_0.JSONFactory_UKOpenBanking_200 diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala index 28f11e297..2ac9c5782 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerJSONFactory.scala @@ -889,7 +889,7 @@ object SwaggerJSONFactory extends MdcLoggable { * @return a list of include original list and nested objects */ private def getAllEntities(entities: List[AnyRef]) = { - val notNullEntities = entities.filter(null !=) + val notNullEntities = entities.filter(null.!=) val notSupportYetEntity = entities.filter(_.getClass.getSimpleName.equals(NotSupportedYet.getClass.getSimpleName.replace("$",""))) val existsEntityTypes: Set[universe.Type] = notNullEntities.map(ReflectUtils.getType).toSet @@ -919,10 +919,10 @@ object SwaggerJSONFactory extends MdcLoggable { val entityType = ReflectUtils.getType(obj) val constructorParamList = ReflectUtils.getPrimaryConstructor(entityType).paramLists.headOption.getOrElse(Nil) // if exclude current obj, the result list tail will be Nil - val resultTail = if(excludeTypes.exists(entityType =:=)) Nil else List(obj) + val resultTail = if(excludeTypes.exists(entityType.=:=)) Nil else List(obj) val refValues: List[Any] = constructorParamList - .filter(it => isSwaggerRefType(it.info) && !excludeTypes.exists(_ =:= it.info)) + .filter(it => isSwaggerRefType(it.info) && !excludeTypes.exists(_.=:=(it.info))) .map(it => { val paramName = it.name.toString val value = ReflectUtils.invokeMethod(obj, paramName) @@ -1009,7 +1009,7 @@ object SwaggerJSONFactory extends MdcLoggable { val errorMessages: Set[AnyRef] = resourceDocList.flatMap(_.error_response_bodies).toSet val errorDefinitions = ErrorMessages.allFields - .filterNot(null ==) + .filterNot(null.==) .filter(it => errorMessages.contains(it._2)) .toList .map(it => { diff --git a/obp-api/src/main/scala/code/api/dynamic/endpoint/helper/DynamicCompileEndpoint.scala b/obp-api/src/main/scala/code/api/dynamic/endpoint/helper/DynamicCompileEndpoint.scala index d052e2169..4022feacd 100644 --- a/obp-api/src/main/scala/code/api/dynamic/endpoint/helper/DynamicCompileEndpoint.scala +++ b/obp-api/src/main/scala/code/api/dynamic/endpoint/helper/DynamicCompileEndpoint.scala @@ -1,5 +1,6 @@ package code.api.dynamic.endpoint.helper +import scala.language.implicitConversions import code.api.util.APIUtil.{OBPEndpoint, OBPReturnType, futureToBoxedResponse, scalaFutureToLaFuture} import code.api.util.DynamicUtil.{Sandbox, Validation} import code.api.util.{CallContext, CustomJsonFormats, DynamicUtil} @@ -34,7 +35,7 @@ trait DynamicCompileEndpoint { } private def validateDependencies() = { - val dependencies = DynamicUtil.getDynamicCodeDependentMethods(this.getClass, "process" == ) + val dependencies = DynamicUtil.getDynamicCodeDependentMethods(this.getClass, "process".==) Validation.validateDependency(dependencies) } } diff --git a/obp-api/src/main/scala/code/api/dynamic/endpoint/helper/DynamicEndpointHelper.scala b/obp-api/src/main/scala/code/api/dynamic/endpoint/helper/DynamicEndpointHelper.scala index 757ea0465..bf423d647 100644 --- a/obp-api/src/main/scala/code/api/dynamic/endpoint/helper/DynamicEndpointHelper.scala +++ b/obp-api/src/main/scala/code/api/dynamic/endpoint/helper/DynamicEndpointHelper.scala @@ -1,5 +1,6 @@ package code.api.dynamic.endpoint.helper +import scala.language.existentials import org.apache.pekko.http.scaladsl.model.{HttpMethods, HttpMethod => PekkoHttpMethod} import code.DynamicData.{DynamicDataProvider, DynamicDataT} import code.DynamicEndpoint.{DynamicEndpointProvider, DynamicEndpointT} @@ -677,7 +678,7 @@ object DynamicEndpointHelper extends RestHelper { schemas += schema } // check whether this schema already recurse two times - if(schemas.count(schema ==) > 3) { + if(schemas.count(schema.==) > 3) { return JObject(Nil) } diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 684290acb..9b27333a7 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -28,6 +28,7 @@ TESOBE (http://www.tesobe.com/) package code.api.util import scala.language.implicitConversions +import scala.language.reflectiveCalls import bootstrap.liftweb.CustomDBVendor import code.accountholders.AccountHolders import code.api.Constant._ @@ -1766,9 +1767,9 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ private val reversedRequestUrl = requestUrlPartPath.reverse def getPathParams(url: List[String]): Map[String, String] = - reversedRequestUrl.zip(url.reverse) collect { + reversedRequestUrl.zip(url.reverse).collect { case pair @(k, _) if isPathVariable(k) => pair - } toMap + }.toMap /** * According errorResponseBodies whether contains UserNotLoggedIn and UserHasMissingRoles do validation. @@ -4024,7 +4025,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ def parseDate(date: String): Option[Date] = { val currentSupportFormats = List(DateWithDayFormat, DateWithSecondsFormat, DateWithMsFormat, DateWithMsRollbackFormat) val parsePosition = new ParsePosition(0) - currentSupportFormats.toStream.map(_.parse(date, parsePosition)).find(null !=) + currentSupportFormats.toStream.map(_.parse(date, parsePosition)).find(null.!=) } private def passesPsd2ServiceProviderCommon(cc: Option[CallContext], serviceProvider: String) = { @@ -4420,7 +4421,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ private def getClassPool(classLoader: ClassLoader) = { import scala.concurrent.duration._ - Caching.memoizeSyncWithImMemory(Some(classLoader.toString()))(DurationInt(30) days) { + Caching.memoizeSyncWithImMemory(Some(classLoader.toString()))(DurationInt(30).days) { val classPool: ClassPool = ClassPool.getDefault classPool.appendClassPath(new LoaderClassPath(classLoader)) classPool @@ -4521,7 +4522,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ */ def getObpTrace(clazzName: String, methodName: String, signature: String, exclude: List[(String, String, String)] = Nil): List[(String, String, String)] = { import scala.concurrent.duration._ - Caching.memoizeSyncWithImMemory(Some(clazzName + methodName + signature))(DurationInt(30) days) { + Caching.memoizeSyncWithImMemory(Some(clazzName + methodName + signature))(DurationInt(30).days) { // List:: className->methodName->signature, find all the dependent methods for one val methods = getDependentMethods(clazzName, methodName, signature) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 80394c0c5..2a684e516 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -3160,7 +3160,7 @@ object NewStyle extends MdcLoggable{ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(methodRoutingTTL second) { + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(methodRoutingTTL.second) { MethodRoutingProvider.connectorMethodProvider.vend.getMethodRoutings(methodName, isBankIdExactMatch, bankIdPattern) } } @@ -3213,7 +3213,7 @@ object NewStyle extends MdcLoggable{ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(endpointMappingTTL second) { + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(endpointMappingTTL.second) { {(EndpointMappingProvider.endpointMappingProvider.vend.getAllEndpointMappings(bankId), callContext)} } } @@ -3327,7 +3327,7 @@ object NewStyle extends MdcLoggable{ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(dynamicEntityTTL second) { + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(dynamicEntityTTL.second) { DynamicEntityProvider.connectorMethodProvider.vend.getDynamicEntities(bankId, returnBothBankAndSystemLevel) } } @@ -3338,7 +3338,7 @@ object NewStyle extends MdcLoggable{ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(dynamicEntityTTL second) { + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(dynamicEntityTTL.second) { DynamicEntityProvider.connectorMethodProvider.vend.getDynamicEntitiesByUserId(userId: String) } } diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index f55e488a2..7a93c9e15 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -76,7 +76,7 @@ trait APIMethods121 { def checkIfLocationPossible(lat:Double,lon:Double) : Box[Unit] = { if(scala.math.abs(lat) <= 90 & scala.math.abs(lon) <= 180) - Full() + Full(()) else Failure("Coordinates not possible") } @@ -132,7 +132,7 @@ trait APIMethods121 { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory.getApiInfoJSON(apiVersion,apiVersionStatus), HttpCode.`200`(cc.callContext)) } diff --git a/obp-api/src/main/scala/code/api/v1_3_0/APIMethods130.scala b/obp-api/src/main/scala/code/api/v1_3_0/APIMethods130.scala index da3ea41bf..5cd2d75cc 100644 --- a/obp-api/src/main/scala/code/api/v1_3_0/APIMethods130.scala +++ b/obp-api/src/main/scala/code/api/v1_3_0/APIMethods130.scala @@ -50,7 +50,7 @@ trait APIMethods130 { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory.getApiInfoJSON(OBPAPI1_3_0.version, OBPAPI1_3_0.versionStatus), HttpCode.`200`(cc.callContext)) } diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index 31d7fe239..b74008028 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -85,7 +85,7 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory.getApiInfoJSON(OBPAPI1_4_0.version, OBPAPI1_4_0.versionStatus), HttpCode.`200`(cc.callContext)) } diff --git a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala index bc2701364..db6f7ee9f 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/JSONFactory1_4_0.scala @@ -530,7 +530,7 @@ object JSONFactory1_4_0 extends MdcLoggable{ jsonResponseBodyFieldsI18n:String ): ResourceDocJson = { val cacheKey = LOCALISED_RESOURCE_DOC_PREFIX + s"operationId:${operationId}-locale:$locale- isVersion4OrHigher:$isVersion4OrHigher".intern() - Caching.memoizeSyncWithImMemory(Some(cacheKey))(CREATE_LOCALISED_RESOURCE_DOC_JSON_TTL seconds) { + Caching.memoizeSyncWithImMemory(Some(cacheKey))(CREATE_LOCALISED_RESOURCE_DOC_JSON_TTL.seconds) { val fieldsDescription = if (resourceDocUpdatedTags.tags.toString.contains("Dynamic-Entity") || resourceDocUpdatedTags.tags.toString.contains("Dynamic-Endpoint") diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index 2ed09e34a..894261e4c 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -148,7 +148,7 @@ trait APIMethods200 { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory121.getApiInfoJSON(OBPAPI2_0_0.version, OBPAPI2_0_0.versionStatus), HttpCode.`200`(cc.callContext)) } diff --git a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala index 4b98fa835..1c83ad6de 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala @@ -92,7 +92,7 @@ trait APIMethods210 { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory.getApiInfoJSON(OBPAPI2_1_0.version, OBPAPI2_1_0.versionStatus), HttpCode.`200`(cc.callContext)) } diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 80ff18aae..0cc651df4 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -80,7 +80,7 @@ trait APIMethods220 { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory.getApiInfoJSON(OBPAPI2_2_0.version, OBPAPI2_2_0.versionStatus), HttpCode.`200`(cc.callContext)) } @@ -536,14 +536,14 @@ trait APIMethods220 { _ <- entitlementsByBank.filter(_.roleName == CanCreateEntitlementAtOneBank.toString()).size > 0 match { case true => // Already has entitlement - Full() + Full(()) case false => Full(Entitlement.entitlement.vend.addEntitlement(bank.id, u.userId, CanCreateEntitlementAtOneBank.toString())) } _ <- entitlementsByBank.filter(_.roleName == CanReadDynamicResourceDocsAtOneBank.toString()).size > 0 match { case true => // Already has entitlement - Full() + Full(()) case false => Full(Entitlement.entitlement.vend.addEntitlement(bank.id, u.userId, CanReadDynamicResourceDocsAtOneBank.toString())) } @@ -1247,7 +1247,7 @@ trait APIMethods220 { (account, callContext) } }else - Future{(Full(), Some(cc))} + Future{(Full(()), Some(cc))} otherAccountRoutingSchemeOBPFormat = if(postJson.other_account_routing_scheme.equalsIgnoreCase("AccountNo")) "ACCOUNT_NUMBER" else StringHelpers.snakify(postJson.other_account_routing_scheme).toUpperCase diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index 7c0be82d2..e556b67ea 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -85,7 +85,7 @@ trait APIMethods300 { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory.getApiInfoJSON(OBPAPI3_0_0.version, OBPAPI3_0_0.versionStatus), HttpCode.`200`(cc.callContext)) } @@ -2119,7 +2119,7 @@ trait APIMethods300 { hasCanReadGlossaryRole } } else { - Future{Full()} + Future{Full(())} } json = JSONFactory300.createGlossaryItemsJsonV300(getGlossaryItems) } yield { diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index cbec5f5b3..0141b3d58 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -102,7 +102,7 @@ trait APIMethods310 { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory.getApiInfoJSON(OBPAPI3_1_0.version, OBPAPI3_1_0.versionStatus), HttpCode.`200`(cc.callContext)) } diff --git a/obp-api/src/main/scala/code/api/v3_1_0/JSONFactory3.1.0.scala b/obp-api/src/main/scala/code/api/v3_1_0/JSONFactory3.1.0.scala index fba8889ad..7cfba9943 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/JSONFactory3.1.0.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/JSONFactory3.1.0.scala @@ -1074,7 +1074,7 @@ object JSONFactory310{ def createEntitlementJsonsV310(tr: List[Entitlement]) = { val idToUser: Map[String, Box[String]] = tr.map(_.userId).distinct.map { userId => (userId, UserX.findByUserId(userId).map(_.name)) - } toMap; + }.toMap; EntitlementJSonsV310( tr.map(e => diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 7453131ba..fa4a35a62 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -1547,7 +1547,7 @@ trait APIMethods400 extends MdcLoggable { value = rejectReasonCode, callContext = callContext ) - } else Future.successful() + } else Future.successful(()) rejectAdditionalInformation = challengeAnswerJson.additional_information.getOrElse("") _ <- @@ -1563,7 +1563,7 @@ trait APIMethods400 extends MdcLoggable { value = rejectAdditionalInformation, callContext = callContext ) - } else Future.successful() + } else Future.successful(()) _ <- NewStyle.function.notifyTransactionRequest( fromAccount, toAccount, @@ -3372,7 +3372,7 @@ trait APIMethods400 extends MdcLoggable { case (Nil | "root" :: Nil) JsonGet _ => { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { ( JSONFactory400.getApiInfoJSON( @@ -3406,7 +3406,7 @@ trait APIMethods400 extends MdcLoggable { case "development" :: "call_context" :: Nil JsonGet _ => { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (cc.callContext, HttpCode.`200`(cc.callContext)) } @@ -3435,7 +3435,7 @@ trait APIMethods400 extends MdcLoggable { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (cc.callContext, HttpCode.`200`(cc.callContext)) } @@ -10458,7 +10458,7 @@ trait APIMethods400 extends MdcLoggable { (account, callContext) } } else - Future { (Full(), Some(cc)) } + Future { (Full(()), Some(cc)) } otherAccountRoutingSchemeOBPFormat = if ( @@ -10811,7 +10811,7 @@ trait APIMethods400 extends MdcLoggable { (account, callContext) } } else - Future { (Full(), Some(cc)) } + Future { (Full(()), Some(cc)) } otherAccountRoutingSchemeOBPFormat = if ( @@ -12873,7 +12873,7 @@ trait APIMethods400 extends MdcLoggable { // auth type validation related endpoints private val allowedAuthTypes = - AuthenticationType.values.filterNot(AuthenticationType.Anonymous ==) + AuthenticationType.values.filterNot(AuthenticationType.Anonymous.==) staticResourceDocs += ResourceDoc( createAuthenticationTypeValidation, implementedInApiVersion, @@ -16725,7 +16725,7 @@ trait APIMethods400 extends MdcLoggable { s"$EntitlementAlreadyExists user_id($userId) ${duplicatedRoles.mkString(",")}" Helper.booleanToFuture(errorMessages, cc = callContext) { false } } else - Future.successful(Full()) + Future.successful(Full(())) } /** This method will check all the roles the loggedIn user already has and the @@ -16759,7 +16759,7 @@ trait APIMethods400 extends MdcLoggable { .mkString(",")}" Helper.booleanToFuture(errorMessages, cc = callContext) { false } } else - Future.successful(Full()) + Future.successful(Full(())) } private def checkRoleBankIdMapping( diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index f7f83ee98..77790a030 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -105,7 +105,7 @@ trait APIMethods500 { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory400.getApiInfoJSON(OBPAPI5_0_0.version,OBPAPI5_0_0.versionStatus), HttpCode.`200`(cc.callContext)) } @@ -221,14 +221,14 @@ trait APIMethods500 { _ <- entitlementsByBank.filter(_.roleName == CanCreateEntitlementAtOneBank.toString()).size > 0 match { case true => // Already has entitlement - Future() + Future(()) case false => Future(Entitlement.entitlement.vend.addEntitlement(postJson.id.getOrElse(""), cc.userId, CanCreateEntitlementAtOneBank.toString())) } _ <- entitlementsByBank.filter(_.roleName == CanReadDynamicResourceDocsAtOneBank.toString()).size > 0 match { case true => // Already has entitlement - Future() + Future(()) case false => Future(Entitlement.entitlement.vend.addEntitlement(postJson.id.getOrElse(""), cc.userId, CanReadDynamicResourceDocsAtOneBank.toString())) } diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 3029949c2..761edf843 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -108,7 +108,7 @@ trait APIMethods510 { case (Nil | "root" :: Nil) JsonGet _ => { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory510.getApiInfoJSON(OBPAPI5_1_0.version,OBPAPI5_1_0.versionStatus), HttpCode.`200`(cc.callContext)) } @@ -4286,7 +4286,7 @@ trait APIMethods510 { case "tags" :: Nil JsonGet _ => cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future.successful() // Just start async call + _ <- Future.successful(()) // Just start async call } yield { (APITags(ApiTag.allDisplayTagNames.toList), HttpCode.`200`(cc.callContext)) } diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 881c93120..a37b92f8c 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -112,7 +112,7 @@ trait APIMethods600 { case (Nil | "root" :: Nil) JsonGet _ => { cc => implicit val ec = EndpointContext(Some(cc)) for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { (JSONFactory510.getApiInfoJSON(OBPAPI6_0_0.version, OBPAPI6_0_0.versionStatus), HttpCode.`200`(cc.callContext)) } @@ -1103,14 +1103,14 @@ trait APIMethods600 { _ <- entitlementsByBank.exists(_.roleName == CanCreateEntitlementAtOneBank.toString()) match { case true => // Already has entitlement - Future() + Future(()) case false => Future(Entitlement.entitlement.vend.addEntitlement(postJson.bank_id, cc.userId, CanCreateEntitlementAtOneBank.toString())) } _ <- entitlementsByBank.exists(_.roleName == CanReadDynamicResourceDocsAtOneBank.toString()) match { case true => // Already has entitlement - Future() + Future(()) case false => Future(Entitlement.entitlement.vend.addEntitlement(postJson.bank_id, cc.userId, CanReadDynamicResourceDocsAtOneBank.toString())) } @@ -1239,7 +1239,7 @@ trait APIMethods600 { */ val cacheKey = "getConnectorMethodNames" val cacheTTL = APIUtil.getPropsAsIntValue("getConnectorMethodNames.cache.ttl.seconds", 3600) - Caching.memoizeSyncWithProvider(Some(cacheKey))(cacheTTL seconds) { + Caching.memoizeSyncWithProvider(Some(cacheKey))(cacheTTL.seconds) { val connectorName = APIUtil.getPropsValue("connector", "mapped") val connector = code.bankconnectors.Connector.getConnectorInstance(connectorName) connector.callableMethods.keys.toList diff --git a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala index 877b91b72..8269843e9 100644 --- a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala +++ b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala @@ -48,7 +48,7 @@ object Http4s700 { val callContext = req.attributes.lookup(callContextKey).get.asInstanceOf[CallContext] Ok(IO.fromFuture(IO( for { - _ <- Future() // Just start async call + _ <- Future(()) // Just start async call } yield { convertAnyToJsonString( JSONFactory700.getApiInfoJSON(apiVersion, s"Hello, ${callContext.userId}! Your request ID is ${callContext.requestId}.") diff --git a/obp-api/src/main/scala/code/authtypevalidation/MappedAuthTypeValidationProvider.scala b/obp-api/src/main/scala/code/authtypevalidation/MappedAuthTypeValidationProvider.scala index 19e7cffd6..6f7d12219 100644 --- a/obp-api/src/main/scala/code/authtypevalidation/MappedAuthTypeValidationProvider.scala +++ b/obp-api/src/main/scala/code/authtypevalidation/MappedAuthTypeValidationProvider.scala @@ -22,7 +22,7 @@ object MappedAuthTypeValidationProvider extends AuthenticationTypeValidationProv override def getByOperationId(operationId: String): Box[JsonAuthTypeValidation] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getValidationByOperationIdTTL second) { + Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getValidationByOperationIdTTL.second) { AuthenticationTypeValidation.find(By(AuthenticationTypeValidation.OperationId, operationId)) .map(it => JsonAuthTypeValidation(it.operationId, it.allowedAuthTypes)) }} diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 4fe2e3b84..8ef5483e3 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1,5 +1,6 @@ package code.bankconnectors +import scala.language.implicitConversions import org.apache.pekko.http.scaladsl.model.HttpMethod import code.api.attributedefinition.AttributeDefinition import code.api.util.APIUtil.{OBPReturnType, _} @@ -220,7 +221,7 @@ trait Connector extends MdcLoggable { protected implicit def OBPReturnTypeToFutureReturnType[T](value: OBPReturnType[Box[T]]): Future[Box[(T, Option[CallContext])]] = value map tupleToBoxTuple - private val futureTimeOut: Duration = 20 seconds + private val futureTimeOut: Duration = 20.seconds /** * convert OBPReturnType return type to Tuple type * @@ -240,7 +241,7 @@ trait Connector extends MdcLoggable { */ protected implicit def OBPReturnTypeToBoxTuple[T](value: OBPReturnType[Box[T]]): Box[(T, Option[CallContext])] = Await.result( - OBPReturnTypeToFutureReturnType(value), 30 seconds + OBPReturnTypeToFutureReturnType(value), 30.seconds ) /** @@ -253,7 +254,7 @@ trait Connector extends MdcLoggable { protected implicit def OBPReturnTypeToBox[T](value: OBPReturnType[Box[T]]): Box[T] = Await.result( value.map(_._1), - 30 seconds + 30.seconds ) protected def convertToTuple[T](callContext: Option[CallContext])(inbound: Box[InBoundTrait[T]]): (Box[T], Option[CallContext]) = { diff --git a/obp-api/src/main/scala/code/bankconnectors/InternalConnector.scala b/obp-api/src/main/scala/code/bankconnectors/InternalConnector.scala index b9d1464a4..d5fac02b5 100644 --- a/obp-api/src/main/scala/code/bankconnectors/InternalConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/InternalConnector.scala @@ -241,19 +241,19 @@ object InternalConnector { val dynamicMethods: Map[String, MethodSymbol] = ConnectorMethodProvider.provider.vend.getAll().map { case JsonConnectorMethod(_, methodName, _, _) => methodName -> Box(methodNameToSymbols.get(methodName)).openOrThrowException(s"method name $methodName does not exist in the Connector") - } toMap + }.toMap dynamicMethods } - private lazy val methodNameToSymbols: Map[String, MethodSymbol] = typeOf[Connector].decls collect { + private lazy val methodNameToSymbols: Map[String, MethodSymbol] = typeOf[Connector].decls.collect { case t: TermSymbol if t.isMethod && t.isPublic && !t.isConstructor && !t.isVal && !t.isVar => val methodName = t.name.decodedName.toString.trim val method = t.asMethod methodName -> method - } toMap + }.toMap - lazy val methodNameToSignature: Map[String, String] = methodNameToSymbols map { + lazy val methodNameToSignature: Map[String, String] = methodNameToSymbols.map { case (methodName, methodSymbol) => val signature = methodSymbol.typeSignature.toString val returnType = methodSymbol.returnType.toString diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnectorInternal.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnectorInternal.scala index 25e48a15f..5313b8926 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnectorInternal.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnectorInternal.scala @@ -947,7 +947,7 @@ object LocalMappedConnectorInternal extends MdcLoggable { attributeType = TransactionRequestAttributeType.withName("STRING"), value = refundReasonCode, callContext = callContext) - } else Future.successful() + } else Future.successful(()) (newTransactionRequestStatus, callContext) <- NewStyle.function.notifyTransactionRequest(refundFromAccount, refundToAccount, createdTransactionRequest, callContext) _ <- NewStyle.function.saveTransactionRequestStatusImpl(createdTransactionRequest.id, newTransactionRequestStatus.toString, callContext) diff --git a/obp-api/src/main/scala/code/bankconnectors/akka/actor/AkkaConnectorActorInit.scala b/obp-api/src/main/scala/code/bankconnectors/akka/actor/AkkaConnectorActorInit.scala index 2170bf622..ec718d31d 100644 --- a/obp-api/src/main/scala/code/bankconnectors/akka/actor/AkkaConnectorActorInit.scala +++ b/obp-api/src/main/scala/code/bankconnectors/akka/actor/AkkaConnectorActorInit.scala @@ -9,5 +9,5 @@ import scala.concurrent.duration._ trait AkkaConnectorActorInit extends MdcLoggable{ // Default is 3 seconds, which should be more than enough for slower systems val ACTOR_TIMEOUT: Long = APIUtil.getPropsAsLongValue("akka_connector.timeout").openOr(3) - implicit val timeout = Timeout(ACTOR_TIMEOUT * (1000 milliseconds)) + implicit val timeout = Timeout(ACTOR_TIMEOUT * (1000.milliseconds)) } \ No newline at end of file diff --git a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala index 26304d01f..c5bd84c1b 100644 --- a/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala +++ b/obp-api/src/main/scala/code/bankconnectors/rest/RestConnector_vMar2019.scala @@ -23,6 +23,7 @@ Osloerstrasse 16/17 Berlin 13359, Germany */ +import scala.language.implicitConversions import _root_.org.apache.pekko.stream.StreamTcpException import org.apache.pekko.http.scaladsl.model._ import org.apache.pekko.http.scaladsl.model.headers.RawHeader diff --git a/obp-api/src/main/scala/code/connectormethod/MappedConnectorMethodProvider.scala b/obp-api/src/main/scala/code/connectormethod/MappedConnectorMethodProvider.scala index caf7cfa0e..426f9b047 100644 --- a/obp-api/src/main/scala/code/connectormethod/MappedConnectorMethodProvider.scala +++ b/obp-api/src/main/scala/code/connectormethod/MappedConnectorMethodProvider.scala @@ -31,14 +31,14 @@ object MappedConnectorMethodProvider extends ConnectorMethodProvider { override def getByMethodNameWithCache(methodName: String): Box[JsonConnectorMethod] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getConnectorMethodTTL second) { + Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getConnectorMethodTTL.second) { getByMethodNameWithoutCache(methodName) }} } override def getAll(): List[JsonConnectorMethod] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getConnectorMethodTTL second) { + Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getConnectorMethodTTL.second) { ConnectorMethod.findAll() .map(it => JsonConnectorMethod(Some(it.ConnectorMethodId.get), it.MethodName.get, it.MethodBody.get, getLang(it))) }} diff --git a/obp-api/src/main/scala/code/dynamicEndpoint/MapppedDynamicEndpointProvider.scala b/obp-api/src/main/scala/code/dynamicEndpoint/MapppedDynamicEndpointProvider.scala index 3ae9f9cc0..d4660d7b5 100644 --- a/obp-api/src/main/scala/code/dynamicEndpoint/MapppedDynamicEndpointProvider.scala +++ b/obp-api/src/main/scala/code/dynamicEndpoint/MapppedDynamicEndpointProvider.scala @@ -71,7 +71,7 @@ object MappedDynamicEndpointProvider extends DynamicEndpointProvider with Custom override def getAll(bankId: Option[String]): List[DynamicEndpointT] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (dynamicEndpointTTL second) { + Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (dynamicEndpointTTL.second) { if (bankId.isEmpty) DynamicEndpoint.findAll() else diff --git a/obp-api/src/main/scala/code/dynamicMessageDoc/MappedDynamicMessageDocProvider.scala b/obp-api/src/main/scala/code/dynamicMessageDoc/MappedDynamicMessageDocProvider.scala index 81b420b27..81240419f 100644 --- a/obp-api/src/main/scala/code/dynamicMessageDoc/MappedDynamicMessageDocProvider.scala +++ b/obp-api/src/main/scala/code/dynamicMessageDoc/MappedDynamicMessageDocProvider.scala @@ -44,7 +44,7 @@ object MappedDynamicMessageDocProvider extends DynamicMessageDocProvider { override def getAll(bankId: Option[String]): List[JsonDynamicMessageDoc] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getDynamicMessageDocTTL second) { + Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getDynamicMessageDocTTL.second) { if(bankId.isEmpty){ DynamicMessageDoc.findAll().map(DynamicMessageDoc.getJsonDynamicMessageDoc) } else { diff --git a/obp-api/src/main/scala/code/dynamicResourceDoc/MappedDynamicResourceDocProvider.scala b/obp-api/src/main/scala/code/dynamicResourceDoc/MappedDynamicResourceDocProvider.scala index 2b545f336..142e64b2e 100644 --- a/obp-api/src/main/scala/code/dynamicResourceDoc/MappedDynamicResourceDocProvider.scala +++ b/obp-api/src/main/scala/code/dynamicResourceDoc/MappedDynamicResourceDocProvider.scala @@ -50,7 +50,7 @@ object MappedDynamicResourceDocProvider extends DynamicResourceDocProvider { override def getAllAndConvert[T: Manifest](bankId: Option[String], transform: JsonDynamicResourceDoc => T): List[T] = { val cacheKey = (bankId.toString+transform.toString()).intern() - Caching.memoizeSyncWithImMemory(Some(cacheKey))(getDynamicResourceDocTTL seconds){ + Caching.memoizeSyncWithImMemory(Some(cacheKey))(getDynamicResourceDocTTL.seconds){ if(bankId.isEmpty){ DynamicResourceDoc.findAll() .map(doc => transform(DynamicResourceDoc.getJsonDynamicResourceDoc(doc))) diff --git a/obp-api/src/main/scala/code/fx/fx.scala b/obp-api/src/main/scala/code/fx/fx.scala index f5a6ec948..9abf2e2f9 100644 --- a/obp-api/src/main/scala/code/fx/fx.scala +++ b/obp-api/src/main/scala/code/fx/fx.scala @@ -66,7 +66,7 @@ object fx extends MdcLoggable { */ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(TTL seconds) { + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(TTL.seconds) { getFallbackExchangeRate(fromCurrency, toCurrency) } } diff --git a/obp-api/src/main/scala/code/management/ImporterAPI.scala b/obp-api/src/main/scala/code/management/ImporterAPI.scala index 3a0fa9e28..0a65a03e0 100644 --- a/obp-api/src/main/scala/code/management/ImporterAPI.scala +++ b/obp-api/src/main/scala/code/management/ImporterAPI.scala @@ -160,7 +160,7 @@ object ImporterAPI extends RestHelper with MdcLoggable { * per "Account". */ // TODO: this duration limit should be fixed - val createdEnvelopes = TransactionInserter !? (3 minutes, toInsert) + val createdEnvelopes = TransactionInserter !? (3.minutes, toInsert) createdEnvelopes match { case Full(inserted : InsertedTransactions) => diff --git a/obp-api/src/main/scala/code/metadata/counterparties/MapperCounterparties.scala b/obp-api/src/main/scala/code/metadata/counterparties/MapperCounterparties.scala index 08c244a22..44d6b5cf4 100644 --- a/obp-api/src/main/scala/code/metadata/counterparties/MapperCounterparties.scala +++ b/obp-api/src/main/scala/code/metadata/counterparties/MapperCounterparties.scala @@ -35,7 +35,7 @@ object MapperCounterparties extends Counterparties with MdcLoggable { */ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(MetadataTTL second) { + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(MetadataTTL.second) { /** * Generates a new alias name that is guaranteed not to collide with any existing public alias names diff --git a/obp-api/src/main/scala/code/metrics/ConnectorMetrics.scala b/obp-api/src/main/scala/code/metrics/ConnectorMetrics.scala index edc8a1de1..9267e18c6 100644 --- a/obp-api/src/main/scala/code/metrics/ConnectorMetrics.scala +++ b/obp-api/src/main/scala/code/metrics/ConnectorMetrics.scala @@ -33,7 +33,7 @@ object ConnectorMetrics extends ConnectorMetricsProvider { */ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cachedAllConnectorMetrics days){ + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cachedAllConnectorMetrics.days){ val limit = queryParams.collect { case OBPLimit(value) => MaxRows[MappedConnectorMetric](value) }.headOption val offset = queryParams.collect { case OBPOffset(value) => StartAt[MappedConnectorMetric](value) }.headOption val fromDate = queryParams.collect { case OBPFromDate(date) => By_>=(MappedConnectorMetric.date, date) }.headOption diff --git a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala index c62a4dc6e..6ccdefb8a 100644 --- a/obp-api/src/main/scala/code/metrics/MappedMetrics.scala +++ b/obp-api/src/main/scala/code/metrics/MappedMetrics.scala @@ -284,7 +284,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) val cacheTTL = determineMetricsCacheTTL(queryParams) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL seconds){ + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL.seconds){ val optionalParams = getQueryParams(queryParams) MappedMetric.findAll(optionalParams: _*) } @@ -339,7 +339,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) val cacheTTL = determineMetricsCacheTTL(queryParams) logger.debug(s"getAllAggregateMetricsBox cache key: $cacheKey, TTL: $cacheTTL seconds") - CacheKeyFromArguments.buildCacheKey { Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL seconds){ + CacheKeyFromArguments.buildCacheKey { Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL.seconds){ logger.info(s"getAllAggregateMetricsBox - CACHE MISS - Executing database query for aggregate metrics") val startTime = System.currentTimeMillis() val fromDate = queryParams.collect { case OBPFromDate(value) => value }.headOption @@ -457,7 +457,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ */ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) val cacheTTL = determineMetricsCacheTTL(queryParams) - CacheKeyFromArguments.buildCacheKey {Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL seconds){ + CacheKeyFromArguments.buildCacheKey {Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL.seconds){ { val fromDate = queryParams.collect { case OBPFromDate(value) => value }.headOption val toDate = queryParams.collect { case OBPToDate(value) => value }.headOption @@ -540,7 +540,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{ */ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) val cacheTTL = determineMetricsCacheTTL(queryParams) - CacheKeyFromArguments.buildCacheKey {Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL seconds){ + CacheKeyFromArguments.buildCacheKey {Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL.seconds){ val fromDate = queryParams.collect { case OBPFromDate(value) => value }.headOption val toDate = queryParams.collect { case OBPToDate(value) => value }.headOption diff --git a/obp-api/src/main/scala/code/model/ModeratedBankingData.scala b/obp-api/src/main/scala/code/model/ModeratedBankingData.scala index 569b48f99..d1623e060 100644 --- a/obp-api/src/main/scala/code/model/ModeratedBankingData.scala +++ b/obp-api/src/main/scala/code/model/ModeratedBankingData.scala @@ -26,6 +26,8 @@ TESOBE (http://www.tesobe.com/) */ package code.model + +import scala.language.implicitConversions import code.api.Constant._ import code.api.util.ErrorMessages._ import code.api.util.{APIUtil, CallContext} @@ -182,6 +184,7 @@ class ModeratedTransactionMetadata( object ModeratedTransactionMetadata { + import scala.language.implicitConversions @deprecated(Helper.deprecatedJsonGenerationMessage) implicit def moderatedTransactionMetadata2Json(mTransactionMeta: ModeratedTransactionMetadata) : JObject = { JObject(JField("blah", JString("test")) :: Nil) @@ -256,6 +259,7 @@ object ModeratedBankAccount { ("name" -> bankName)) } + import scala.language.implicitConversions @deprecated(Helper.deprecatedJsonGenerationMessage) implicit def moderatedBankAccount2Json(mBankAccount: ModeratedBankAccount) : JObject = { val holderName = mBankAccount.owners match{ @@ -318,6 +322,7 @@ case class ModeratedOtherBankAccountCore( } object ModeratedOtherBankAccount { + import scala.language.implicitConversions @deprecated(Helper.deprecatedJsonGenerationMessage) implicit def moderatedOtherBankAccount2Json(mOtherBank: ModeratedOtherBankAccount) : JObject = { val holderName = mOtherBank.label.display @@ -353,6 +358,7 @@ class ModeratedOtherBankAccountMetadata( ) object ModeratedOtherBankAccountMetadata { + import scala.language.implicitConversions @deprecated(Helper.deprecatedJsonGenerationMessage) implicit def moderatedOtherBankAccountMetadata2Json(mOtherBankMeta: ModeratedOtherBankAccountMetadata) : JObject = { JObject(JField("blah", JString("test")) :: Nil) diff --git a/obp-api/src/main/scala/code/model/OAuth.scala b/obp-api/src/main/scala/code/model/OAuth.scala index f5b1b8c65..25d0f3046 100644 --- a/obp-api/src/main/scala/code/model/OAuth.scala +++ b/obp-api/src/main/scala/code/model/OAuth.scala @@ -299,7 +299,7 @@ object MappedConsumersProvider extends ConsumersProvider with MdcLoggable { if(integrateWithHydra && isActive.isDefined) { val clientId = c.key.get val existsOAuth2Client = Box.tryo(hydraAdmin.getOAuth2Client(clientId)) - .filter(null !=) + .filter(null.!=) // TODO Involve Hydra ORY version with working update mechanism if (isActive == Some(false) && existsOAuth2Client.isDefined) { existsOAuth2Client @@ -955,7 +955,7 @@ class Token extends LongKeyedMapper[Token]{ } def generateThirdPartyApplicationSecret: String = { - if(thirdPartyApplicationSecret.get isEmpty){ + if(thirdPartyApplicationSecret.get.isEmpty){ def r() = randomInt(9).toString //from zero to 9 val generatedSecret = (1 to 10).map(x => r()).foldLeft("")(_ + _) thirdPartyApplicationSecret(generatedSecret).save diff --git a/obp-api/src/main/scala/code/model/View.scala b/obp-api/src/main/scala/code/model/View.scala index b7d9d4ebd..bbb44d32a 100644 --- a/obp-api/src/main/scala/code/model/View.scala +++ b/obp-api/src/main/scala/code/model/View.scala @@ -505,6 +505,7 @@ case class ViewExtended(val view: View) extends MdcLoggable { None } + import scala.language.implicitConversions implicit def optionStringToString(x : Option[String]) : String = x.getOrElse("") val otherAccountNationalIdentifier = if(viewPermissions.exists(_ == CAN_SEE_OTHER_ACCOUNT_NATIONAL_IDENTIFIER)) Some(otherBankAccount.nationalIdentifier) else None val otherAccountSWIFT_BIC = if(viewPermissions.exists(_ == CAN_SEE_OTHER_ACCOUNT_SWIFT_BIC)) otherBankAccount.otherBankRoutingAddress else None @@ -607,6 +608,7 @@ case class ViewExtended(val view: View) extends MdcLoggable { None } + import scala.language.implicitConversions implicit def optionStringToString(x : Option[String]) : String = x.getOrElse("") val otherAccountSWIFT_BIC = if(viewPermissions.exists(_ == CAN_SEE_OTHER_ACCOUNT_SWIFT_BIC)) counterpartyCore.otherBankRoutingAddress else None val otherAccountIBAN = if(viewPermissions.exists(_ == CAN_SEE_OTHER_ACCOUNT_IBAN)) counterpartyCore.otherAccountRoutingAddress else None diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index ee6d171a3..11efcde0d 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -347,7 +347,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with CreatedUpdated with MdcLogga } override def save(): Boolean = { - if(! (user defined_?)){ + if(! (user.defined_?)){ logger.info("user reference is null. We will create a ResourceUser") val resourceUser = createUnsavedResourceUser() val savedUser = Users.users.vend.saveResourceUser(resourceUser) diff --git a/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala b/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala index 5b0174c21..810d1bc6c 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/ResourceUser.scala @@ -139,7 +139,7 @@ object ResourceUser extends ResourceUser with LongKeyedMetaMapper[ResourceUser]{ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) val cacheTTL = APIUtil.getPropsAsIntValue("getDistinctProviders.cache.ttl.seconds", 3600) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL seconds) { + Caching.memoizeSyncWithProvider(Some(cacheKey.toString()))(cacheTTL.seconds) { val sql = "SELECT DISTINCT provider_ FROM resourceuser ORDER BY provider_" val (_, rows) = DB.runQuery(sql, List()) rows.flatten diff --git a/obp-api/src/main/scala/code/model/package.scala b/obp-api/src/main/scala/code/model/package.scala index 2f79aed10..4f2626c13 100644 --- a/obp-api/src/main/scala/code/model/package.scala +++ b/obp-api/src/main/scala/code/model/package.scala @@ -1,5 +1,6 @@ package code +import scala.language.implicitConversions import code.metadata.comments.Comments import code.metadata.counterparties.Counterparties import code.metadata.narrative.Narrative @@ -16,6 +17,7 @@ import com.openbankproject.commons.model._ * Bank -> Bank + BankEx */ package object model { + import scala.language.implicitConversions implicit def toBankExtended(bank: Bank) = BankExtended(bank) diff --git a/obp-api/src/main/scala/code/obp/grpc/Client.scala b/obp-api/src/main/scala/code/obp/grpc/Client.scala index 9d81a57bd..c8209f6c1 100644 --- a/obp-api/src/main/scala/code/obp/grpc/Client.scala +++ b/obp-api/src/main/scala/code/obp/grpc/Client.scala @@ -1,5 +1,6 @@ package code.obp.grpc +import scala.language.existentials import code.obp.grpc.api._ import com.google.protobuf.empty.Empty import io.grpc.{ManagedChannel, ManagedChannelBuilder} diff --git a/obp-api/src/main/scala/code/obp/grpc/HelloWorldServer.scala b/obp-api/src/main/scala/code/obp/grpc/HelloWorldServer.scala index 773b60f60..c77752fc5 100644 --- a/obp-api/src/main/scala/code/obp/grpc/HelloWorldServer.scala +++ b/obp-api/src/main/scala/code/obp/grpc/HelloWorldServer.scala @@ -1,5 +1,7 @@ package code.obp.grpc +import scala.language.existentials +import scala.language.reflectiveCalls import code.api.util.newstyle.ViewNewStyle import code.api.util.{APIUtil, CallContext, NewStyle} import code.api.v3_0_0.{CoreTransactionsJsonV300, ModeratedTransactionCoreWithAttributes} diff --git a/obp-api/src/main/scala/code/search/search.scala b/obp-api/src/main/scala/code/search/search.scala index 5c37eeaa9..e99dddf3d 100644 --- a/obp-api/src/main/scala/code/search/search.scala +++ b/obp-api/src/main/scala/code/search/search.scala @@ -185,13 +185,13 @@ class elasticsearch extends MdcLoggable { } private def getParameters(queryString: String): Map[String, String] = { - val res = queryString.split('&') map { str => + val res = queryString.split('&').map { str => val pair = str.split('=') if (pair.length > 1) (pair(0) -> pair(1)) else (pair(0) -> "") - } toMap + }.toMap res } diff --git a/obp-api/src/main/scala/code/snippet/GetHtmlFromUrl.scala b/obp-api/src/main/scala/code/snippet/GetHtmlFromUrl.scala index b1016ffa1..2d4b82f5e 100644 --- a/obp-api/src/main/scala/code/snippet/GetHtmlFromUrl.scala +++ b/obp-api/src/main/scala/code/snippet/GetHtmlFromUrl.scala @@ -55,7 +55,7 @@ object GetHtmlFromUrl extends MdcLoggable { logger.debug("jsVendorSupportHtml: " + jsVendorSupportHtml) // sleep for up to 5 seconds at development environment - if (Props.mode == Props.RunModes.Development) Thread.sleep(randomLong(3 seconds)) + if (Props.mode == Props.RunModes.Development) Thread.sleep(randomLong(3.seconds)) jsVendorSupportHtml } diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index c741558c5..c8861688b 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -654,7 +654,7 @@ class WebUI extends MdcLoggable{ val html = XML.loadString(htmlString) // Sleep if in development environment so can see the effects of content loading slowly - if (Props.mode == Props.RunModes.Development) Thread.sleep(10 seconds) + if (Props.mode == Props.RunModes.Development) Thread.sleep(10.seconds) // Return the HTML html diff --git a/obp-api/src/main/scala/code/util/AkkaHttpClient.scala b/obp-api/src/main/scala/code/util/AkkaHttpClient.scala index 946c1a92b..46d229784 100644 --- a/obp-api/src/main/scala/code/util/AkkaHttpClient.scala +++ b/obp-api/src/main/scala/code/util/AkkaHttpClient.scala @@ -52,7 +52,7 @@ object AkkaHttpClient extends MdcLoggable with CustomJsonFormats { private lazy val connectionPoolSettings: ConnectionPoolSettings = { val systemConfig = ConnectionPoolSettings(system.settings.config) //Note: get the timeout setting from here: https://github.com/akka/akka-http/issues/742 - val clientSettings = systemConfig.connectionSettings.withIdleTimeout(httpRequestTimeout seconds) + val clientSettings = systemConfig.connectionSettings.withIdleTimeout(httpRequestTimeout.seconds) // reset some settings value systemConfig.copy( /* diff --git a/obp-api/src/main/scala/code/util/Helper.scala b/obp-api/src/main/scala/code/util/Helper.scala index e2dd61562..51802a0ac 100644 --- a/obp-api/src/main/scala/code/util/Helper.scala +++ b/obp-api/src/main/scala/code/util/Helper.scala @@ -89,14 +89,14 @@ object Helper extends Loggable { */ def booleanToBox(statement: => Boolean, msg: String): Box[Unit] = { if(statement) - Full() + Full(()) else Failure(msg) } def booleanToBox(statement: => Boolean): Box[Unit] = { if(statement) - Full() + Full(()) else Empty } @@ -450,7 +450,7 @@ object Helper extends Loggable { def getRequiredFieldInfo(tpe: Type): RequiredInfo = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - code.api.cache.Caching.memoizeSyncWithImMemory (Some(cacheKey.toString())) (100000 days) { + code.api.cache.Caching.memoizeSyncWithImMemory (Some(cacheKey.toString())) (100000.days) { RequiredFieldValidation.getRequiredInfo(tpe) diff --git a/obp-api/src/main/scala/code/validation/MappedJsonSchemaValidationProvider.scala b/obp-api/src/main/scala/code/validation/MappedJsonSchemaValidationProvider.scala index 53538d152..17f7a663e 100644 --- a/obp-api/src/main/scala/code/validation/MappedJsonSchemaValidationProvider.scala +++ b/obp-api/src/main/scala/code/validation/MappedJsonSchemaValidationProvider.scala @@ -20,7 +20,7 @@ object MappedJsonSchemaValidationProvider extends JsonSchemaValidationProvider { override def getByOperationId(operationId: String): Box[JsonValidation] = { var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getValidationByOperationIdTTL second) { + Caching.memoizeSyncWithProvider (Some(cacheKey.toString())) (getValidationByOperationIdTTL.second) { JsonSchemaValidation.find(By(JsonSchemaValidation.OperationId, operationId)) .map(it => JsonValidation(it.operationId, it.jsonSchema)) }} diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 19e7d1c4e..01cacb7d6 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -469,7 +469,7 @@ object MapperViews extends Views with MdcLoggable { viewId ).length > 0 match { case true => Failure("Account Access record uses this View.") // We want to prevent account access orphans - case false => Full() + case false => Full(()) } } yield { customView.deleteViewPermissions @@ -481,7 +481,7 @@ object MapperViews extends Views with MdcLoggable { view <- ViewDefinition.findSystemView(viewId.value) _ <- AccountAccess.findAllBySystemViewId(viewId).length > 0 match { case true => Failure("Account Access record uses this View.") // We want to prevent account access orphans - case false => Full() + case false => Full(()) } } yield { view.deleteViewPermissions diff --git a/obp-api/src/main/scala/code/webuiprops/MappedWebUiPropsProvider.scala b/obp-api/src/main/scala/code/webuiprops/MappedWebUiPropsProvider.scala index cec35e7c0..93b7516be 100644 --- a/obp-api/src/main/scala/code/webuiprops/MappedWebUiPropsProvider.scala +++ b/obp-api/src/main/scala/code/webuiprops/MappedWebUiPropsProvider.scala @@ -42,7 +42,7 @@ object MappedWebUiPropsProvider extends WebUiPropsProvider { import scala.concurrent.duration._ var cacheKey = (randomUUID().toString, randomUUID().toString, randomUUID().toString) CacheKeyFromArguments.buildCacheKey { - Caching.memoizeSyncWithImMemory(Some(cacheKey.toString()))(webUiPropsTTL second) { + Caching.memoizeSyncWithImMemory(Some(cacheKey.toString()))(webUiPropsTTL.second) { // If we have an active brand, construct a target property name to look for. val brandSpecificPropertyName = activeBrand() match { case Some(brand) => s"${requestedPropertyName}_FOR_BRAND_${brand}" From a366afaad4ab5de85ac06bdb6059ccaefe94ee2d Mon Sep 17 00:00:00 2001 From: simonredfern Date: Thu, 1 Jan 2026 03:22:28 +0100 Subject: [PATCH 08/48] Tests for cache info etc --- .../code/api/v6_0_0/CacheEndpointsTest.scala | 353 ++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala diff --git a/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala new file mode 100644 index 000000000..8b40957db --- /dev/null +++ b/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala @@ -0,0 +1,353 @@ +/** +Open Bank Project - API +Copyright (C) 2011-2024, 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 . + +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.v6_0_0 + +import code.api.util.APIUtil.OAuth._ +import code.api.util.ApiRole.{CanGetCacheConfig, CanGetCacheInfo, CanInvalidateCacheNamespace} +import code.api.util.ErrorMessages.{InvalidJsonFormat, UserHasMissingRoles, UserNotLoggedIn} +import code.api.v6_0_0.OBPAPI6_0_0.Implementations6_0_0 +import code.entitlement.Entitlement +import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.model.ErrorMessage +import com.openbankproject.commons.util.ApiVersion +import net.liftweb.json.Serialization.write +import org.scalatest.Tag + +class CacheEndpointsTest extends V600ServerSetup { + /** + * Test tags + * Example: To run tests with tag "getCacheConfig": + * mvn test -D tagsToInclude + * + * This is made possible by the scalatest maven plugin + */ + object VersionOfApi extends Tag(ApiVersion.v6_0_0.toString) + object ApiEndpoint1 extends Tag(nameOf(Implementations6_0_0.getCacheConfig)) + object ApiEndpoint2 extends Tag(nameOf(Implementations6_0_0.getCacheInfo)) + object ApiEndpoint3 extends Tag(nameOf(Implementations6_0_0.invalidateCacheNamespace)) + + // ============================================================================================================ + // GET /system/cache/config - Get Cache Configuration + // ============================================================================================================ + + feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") { + scenario("We call getCacheConfig without user credentials", ApiEndpoint1, VersionOfApi) { + When("We make a request v6.0.0 without credentials") + val request = (v6_0_0_Request / "system" / "cache" / "config").GET + val response = makeGetRequest(request) + Then("We should get a 401") + response.code should equal(401) + response.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + } + + feature(s"test $ApiEndpoint1 version $VersionOfApi - Missing role") { + scenario("We call getCacheConfig without the CanGetCacheConfig role", ApiEndpoint1, VersionOfApi) { + When("We make a request v6.0.0 without the required role") + val request = (v6_0_0_Request / "system" / "cache" / "config").GET <@ (user1) + val response = makeGetRequest(request) + Then("We should get a 403") + response.code should equal(403) + And("error should be " + UserHasMissingRoles + CanGetCacheConfig) + response.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanGetCacheConfig) + } + } + + feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access") { + scenario("We call getCacheConfig with the CanGetCacheConfig role", ApiEndpoint1, VersionOfApi) { + Given("We have a user with CanGetCacheConfig entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetCacheConfig.toString) + + When("We make a request v6.0.0 with proper role") + val request = (v6_0_0_Request / "system" / "cache" / "config").GET <@ (user1) + val response = makeGetRequest(request) + + Then("We should get a 200") + response.code should equal(200) + + And("The response should have the correct structure") + val cacheConfig = response.body.extract[CacheConfigJsonV600] + cacheConfig.providers should not be empty + cacheConfig.instance_id should not be empty + cacheConfig.environment should not be empty + cacheConfig.global_prefix should not be empty + + And("Providers should have valid data") + cacheConfig.providers.foreach { provider => + provider.provider should not be empty + provider.enabled shouldBe a[Boolean] + } + } + } + + // ============================================================================================================ + // GET /system/cache/info - Get Cache Information + // ============================================================================================================ + + feature(s"test $ApiEndpoint2 version $VersionOfApi - Unauthorized access") { + scenario("We call getCacheInfo without user credentials", ApiEndpoint2, VersionOfApi) { + When("We make a request v6.0.0 without credentials") + val request = (v6_0_0_Request / "system" / "cache" / "info").GET + val response = makeGetRequest(request) + Then("We should get a 401") + response.code should equal(401) + response.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + } + + feature(s"test $ApiEndpoint2 version $VersionOfApi - Missing role") { + scenario("We call getCacheInfo without the CanGetCacheInfo role", ApiEndpoint2, VersionOfApi) { + When("We make a request v6.0.0 without the required role") + val request = (v6_0_0_Request / "system" / "cache" / "info").GET <@ (user1) + val response = makeGetRequest(request) + Then("We should get a 403") + response.code should equal(403) + And("error should be " + UserHasMissingRoles + CanGetCacheInfo) + response.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanGetCacheInfo) + } + } + + feature(s"test $ApiEndpoint2 version $VersionOfApi - Authorized access") { + scenario("We call getCacheInfo with the CanGetCacheInfo role", ApiEndpoint2, VersionOfApi) { + Given("We have a user with CanGetCacheInfo entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetCacheInfo.toString) + + When("We make a request v6.0.0 with proper role") + val request = (v6_0_0_Request / "system" / "cache" / "info").GET <@ (user1) + val response = makeGetRequest(request) + + Then("We should get a 200") + response.code should equal(200) + + And("The response should have the correct structure") + val cacheInfo = response.body.extract[CacheInfoJsonV600] + cacheInfo.namespaces should not be null + cacheInfo.total_keys should be >= 0 + cacheInfo.redis_available shouldBe a[Boolean] + + And("Each namespace should have valid data") + cacheInfo.namespaces.foreach { namespace => + namespace.namespace_id should not be empty + namespace.prefix should not be empty + namespace.current_version should be > 0L + namespace.key_count should be >= 0 + namespace.description should not be empty + namespace.category should not be empty + } + } + } + + // ============================================================================================================ + // POST /management/cache/namespaces/invalidate - Invalidate Cache Namespace + // ============================================================================================================ + + feature(s"test $ApiEndpoint3 version $VersionOfApi - Unauthorized access") { + scenario("We call invalidateCacheNamespace without user credentials", ApiEndpoint3, VersionOfApi) { + When("We make a request v6.0.0 without credentials") + val request = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST + val response = makePostRequest(request, write(InvalidateCacheNamespaceJsonV600("rd_localised"))) + Then("We should get a 401") + response.code should equal(401) + response.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + } + + feature(s"test $ApiEndpoint3 version $VersionOfApi - Missing role") { + scenario("We call invalidateCacheNamespace without the CanInvalidateCacheNamespace role", ApiEndpoint3, VersionOfApi) { + When("We make a request v6.0.0 without the required role") + val request = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val response = makePostRequest(request, write(InvalidateCacheNamespaceJsonV600("rd_localised"))) + Then("We should get a 403") + response.code should equal(403) + And("error should be " + UserHasMissingRoles + CanInvalidateCacheNamespace) + response.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanInvalidateCacheNamespace) + } + } + + feature(s"test $ApiEndpoint3 version $VersionOfApi - Invalid JSON format") { + scenario("We call invalidateCacheNamespace with invalid JSON", ApiEndpoint3, VersionOfApi) { + Given("We have a user with CanInvalidateCacheNamespace entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanInvalidateCacheNamespace.toString) + + When("We make a request with invalid JSON") + val request = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val response = makePostRequest(request, """{"invalid": "json"}""") + + Then("We should get a 400") + response.code should equal(400) + And("error should be InvalidJsonFormat") + response.body.extract[ErrorMessage].message should startWith(InvalidJsonFormat) + } + } + + feature(s"test $ApiEndpoint3 version $VersionOfApi - Invalid namespace_id") { + scenario("We call invalidateCacheNamespace with non-existent namespace_id", ApiEndpoint3, VersionOfApi) { + Given("We have a user with CanInvalidateCacheNamespace entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanInvalidateCacheNamespace.toString) + + When("We make a request with invalid namespace_id") + val request = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val response = makePostRequest(request, write(InvalidateCacheNamespaceJsonV600("invalid_namespace"))) + + Then("We should get a 400") + response.code should equal(400) + And("error should mention invalid namespace_id") + val errorMessage = response.body.extract[ErrorMessage].message + errorMessage should include("Invalid namespace_id") + errorMessage should include("invalid_namespace") + } + } + + feature(s"test $ApiEndpoint3 version $VersionOfApi - Authorized access with valid namespace") { + scenario("We call invalidateCacheNamespace with valid rd_localised namespace", ApiEndpoint3, VersionOfApi) { + Given("We have a user with CanInvalidateCacheNamespace entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanInvalidateCacheNamespace.toString) + + When("We make a request with valid namespace_id") + val request = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val response = makePostRequest(request, write(InvalidateCacheNamespaceJsonV600("rd_localised"))) + + Then("We should get a 200") + response.code should equal(200) + + And("The response should have the correct structure") + val result = response.body.extract[InvalidatedCacheNamespaceJsonV600] + result.namespace_id should equal("rd_localised") + result.old_version should be > 0L + result.new_version should be > result.old_version + result.new_version should equal(result.old_version + 1) + result.status should equal("invalidated") + } + + scenario("We call invalidateCacheNamespace with valid connector namespace", ApiEndpoint3, VersionOfApi) { + Given("We have a user with CanInvalidateCacheNamespace entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanInvalidateCacheNamespace.toString) + + When("We make a request with connector namespace_id") + val request = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val response = makePostRequest(request, write(InvalidateCacheNamespaceJsonV600("connector"))) + + Then("We should get a 200") + response.code should equal(200) + + And("The response should have the correct structure") + val result = response.body.extract[InvalidatedCacheNamespaceJsonV600] + result.namespace_id should equal("connector") + result.old_version should be > 0L + result.new_version should be > result.old_version + result.status should equal("invalidated") + } + + scenario("We call invalidateCacheNamespace with valid abac_rule namespace", ApiEndpoint3, VersionOfApi) { + Given("We have a user with CanInvalidateCacheNamespace entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanInvalidateCacheNamespace.toString) + + When("We make a request with abac_rule namespace_id") + val request = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val response = makePostRequest(request, write(InvalidateCacheNamespaceJsonV600("abac_rule"))) + + Then("We should get a 200") + response.code should equal(200) + + And("The response should have the correct structure") + val result = response.body.extract[InvalidatedCacheNamespaceJsonV600] + result.namespace_id should equal("abac_rule") + result.status should equal("invalidated") + } + } + + feature(s"test $ApiEndpoint3 version $VersionOfApi - Version increment validation") { + scenario("We verify that cache version increments correctly on multiple invalidations", ApiEndpoint3, VersionOfApi) { + Given("We have a user with CanInvalidateCacheNamespace entitlement") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanInvalidateCacheNamespace.toString) + + When("We invalidate the same namespace twice") + val request1 = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val response1 = makePostRequest(request1, write(InvalidateCacheNamespaceJsonV600("rd_dynamic"))) + + Then("First invalidation should succeed") + response1.code should equal(200) + val result1 = response1.body.extract[InvalidatedCacheNamespaceJsonV600] + val firstNewVersion = result1.new_version + + When("We invalidate again") + val request2 = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val response2 = makePostRequest(request2, write(InvalidateCacheNamespaceJsonV600("rd_dynamic"))) + + Then("Second invalidation should succeed") + response2.code should equal(200) + val result2 = response2.body.extract[InvalidatedCacheNamespaceJsonV600] + + And("Version should have incremented again") + result2.old_version should equal(firstNewVersion) + result2.new_version should equal(firstNewVersion + 1) + result2.status should equal("invalidated") + } + } + + // ============================================================================================================ + // Cross-endpoint test - Verify cache info updates after invalidation + // ============================================================================================================ + + feature(s"Integration test - Cache endpoints interaction") { + scenario("We verify cache info shows updated version after invalidation", ApiEndpoint2, ApiEndpoint3, VersionOfApi) { + Given("We have a user with both CanGetCacheInfo and CanInvalidateCacheNamespace entitlements") + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetCacheInfo.toString) + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanInvalidateCacheNamespace.toString) + + When("We get the initial cache info") + val getRequest1 = (v6_0_0_Request / "system" / "cache" / "info").GET <@ (user1) + val getResponse1 = makeGetRequest(getRequest1) + getResponse1.code should equal(200) + val cacheInfo1 = getResponse1.body.extract[CacheInfoJsonV600] + + // Find the rd_static namespace (or any other valid namespace) + val targetNamespace = "rd_static" + val initialVersion = cacheInfo1.namespaces.find(_.namespace_id == targetNamespace).map(_.current_version) + + When("We invalidate the namespace") + val invalidateRequest = (v6_0_0_Request / "management" / "cache" / "namespaces" / "invalidate").POST <@ (user1) + val invalidateResponse = makePostRequest(invalidateRequest, write(InvalidateCacheNamespaceJsonV600(targetNamespace))) + invalidateResponse.code should equal(200) + val invalidateResult = invalidateResponse.body.extract[InvalidatedCacheNamespaceJsonV600] + + When("We get the cache info again") + val getRequest2 = (v6_0_0_Request / "system" / "cache" / "info").GET <@ (user1) + val getResponse2 = makeGetRequest(getRequest2) + getResponse2.code should equal(200) + val cacheInfo2 = getResponse2.body.extract[CacheInfoJsonV600] + + Then("The namespace version should have been incremented") + val updatedNamespace = cacheInfo2.namespaces.find(_.namespace_id == targetNamespace) + updatedNamespace should not be None + + if (initialVersion.isDefined) { + updatedNamespace.get.current_version should be > initialVersion.get + } + updatedNamespace.get.current_version should equal(invalidateResult.new_version) + } + } +} From 5e00e012dbead3034e3fc89f4f75bf5085cd1472 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Thu, 1 Jan 2026 03:40:41 +0100 Subject: [PATCH 09/48] Cache info storage_location --- .../main/scala/code/api/cache/InMemory.scala | 18 ++++++++ .../scala/code/api/v6_0_0/APIMethods600.scala | 11 ++++- .../code/api/v6_0_0/JSONFactory6.0.0.scala | 45 +++++++++++++++---- .../code/api/v6_0_0/CacheEndpointsTest.scala | 2 + 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/obp-api/src/main/scala/code/api/cache/InMemory.scala b/obp-api/src/main/scala/code/api/cache/InMemory.scala index ba86bbfa6..9c4054430 100644 --- a/obp-api/src/main/scala/code/api/cache/InMemory.scala +++ b/obp-api/src/main/scala/code/api/cache/InMemory.scala @@ -25,4 +25,22 @@ object InMemory extends MdcLoggable { logger.trace(s"InMemory.memoizeWithInMemory.underlyingGuavaCache size ${underlyingGuavaCache.size()}, current cache key is $cacheKey") memoize(ttl)(f) } + + /** + * Count keys matching a pattern in the in-memory cache + * @param pattern Pattern to match (supports * wildcard) + * @return Number of matching keys + */ + def countKeys(pattern: String): Int = { + try { + val regex = pattern.replace("*", ".*").r + val allKeys = underlyingGuavaCache.asMap().keySet() + import scala.collection.JavaConverters._ + allKeys.asScala.count(key => regex.pattern.matcher(key).matches()) + } catch { + case e: Throwable => + logger.error(s"Error counting in-memory cache keys for pattern $pattern: ${e.getMessage}") + 0 + } + } } diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 70a3f3565..02c824ce0 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -733,6 +733,11 @@ trait APIMethods600 { |- Current version counter |- Number of keys in each namespace |- Description and category + |- Storage location (redis, memory, both, or unknown) + | - "redis": Keys stored in Redis + | - "memory": Keys stored in in-memory cache + | - "both": Keys in both locations (indicates a BUG - should never happen) + | - "unknown": No keys found, storage location cannot be determined |- Total key count across all namespaces |- Redis availability status | @@ -749,7 +754,8 @@ trait APIMethods600 { current_version = 1, key_count = 42, description = "Rate limit call counters", - category = "Rate Limiting" + category = "Rate Limiting", + storage_location = "redis" ), CacheNamespaceInfoJsonV600( namespace_id = "rd_localised", @@ -757,7 +763,8 @@ trait APIMethods600 { current_version = 1, key_count = 128, description = "Localized resource docs", - category = "API Documentation" + category = "API Documentation", + storage_location = "redis" ) ), total_keys = 170, diff --git a/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala b/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala index ae8587f8b..2a29d7a96 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala @@ -289,7 +289,8 @@ case class CacheNamespaceInfoJsonV600( current_version: Long, key_count: Int, description: String, - category: String + category: String, + storage_location: String ) case class CacheInfoJsonV600( @@ -1153,7 +1154,7 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { } def createCacheInfoJsonV600(): CacheInfoJsonV600 = { - import code.api.cache.Redis + import code.api.cache.{Redis, InMemory} import code.api.Constant val namespaceDescriptions = Map( @@ -1178,14 +1179,41 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { val prefix = Constant.getVersionedCachePrefix(namespaceId) val pattern = s"${prefix}*" - val keyCount = try { - val count = Redis.countKeys(pattern) - totalKeys += count - count + // Dynamically determine storage location by checking where keys exist + var redisKeyCount = 0 + var memoryKeyCount = 0 + var storageLocation = "unknown" + + try { + redisKeyCount = Redis.countKeys(pattern) + totalKeys += redisKeyCount } catch { case _: Throwable => redisAvailable = false - 0 + } + + try { + memoryKeyCount = InMemory.countKeys(pattern) + totalKeys += memoryKeyCount + } catch { + case _: Throwable => + // In-memory cache error (shouldn't happen, but handle gracefully) + } + + // Determine storage based on where keys actually exist + val keyCount = if (redisKeyCount > 0 && memoryKeyCount > 0) { + storageLocation = "both" + redisKeyCount + memoryKeyCount + } else if (redisKeyCount > 0) { + storageLocation = "redis" + redisKeyCount + } else if (memoryKeyCount > 0) { + storageLocation = "memory" + memoryKeyCount + } else { + // No keys found in either location - we don't know where they would be stored + storageLocation = "unknown" + 0 } val (description, category) = namespaceDescriptions.getOrElse(namespaceId, ("Unknown namespace", "Other")) @@ -1196,7 +1224,8 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { current_version = version, key_count = keyCount, description = description, - category = category + category = category, + storage_location = storageLocation ) } diff --git a/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala index 8b40957db..ee8460f73 100644 --- a/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala +++ b/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala @@ -156,6 +156,8 @@ class CacheEndpointsTest extends V600ServerSetup { namespace.key_count should be >= 0 namespace.description should not be empty namespace.category should not be empty + namespace.storage_location should not be empty + namespace.storage_location should (equal("redis") or equal("memory") or equal("both") or equal("unknown")) } } } From f365523360aa4bd159df7ddd20dea063d447739f Mon Sep 17 00:00:00 2001 From: simonredfern Date: Thu, 1 Jan 2026 04:34:55 +0100 Subject: [PATCH 10/48] System Cache Config fields --- .../scala/code/api/v6_0_0/APIMethods600.scala | 37 ++++---- .../code/api/v6_0_0/JSONFactory6.0.0.scala | 93 ++++++++++++++----- .../code/api/v6_0_0/CacheEndpointsTest.scala | 2 + 3 files changed, 89 insertions(+), 43 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 02c824ce0..69190fb78 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -667,8 +667,8 @@ trait APIMethods600 { "Get Cache Configuration", """Returns cache configuration information including: | - |- Available cache providers (Redis, In-Memory) - |- Redis connection details (URL, port, SSL) + |- Redis status: availability, connection details (URL, port, SSL) + |- In-memory cache status: availability and current size |- Instance ID and environment |- Global cache namespace prefix | @@ -678,21 +678,15 @@ trait APIMethods600 { |""", EmptyBody, CacheConfigJsonV600( - providers = List( - CacheProviderConfigJsonV600( - provider = "redis", - enabled = true, - url = Some("127.0.0.1"), - port = Some(6379), - use_ssl = Some(false) - ), - CacheProviderConfigJsonV600( - provider = "in_memory", - enabled = true, - url = None, - port = None, - use_ssl = None - ) + redis_status = RedisCacheStatusJsonV600( + available = true, + url = "127.0.0.1", + port = 6379, + use_ssl = false + ), + in_memory_status = InMemoryCacheStatusJsonV600( + available = true, + current_size = 42 ), instance_id = "obp", environment = "dev", @@ -738,6 +732,9 @@ trait APIMethods600 { | - "memory": Keys stored in in-memory cache | - "both": Keys in both locations (indicates a BUG - should never happen) | - "unknown": No keys found, storage location cannot be determined + |- TTL info: Sampled TTL information from actual keys + | - Shows actual TTL values from up to 5 sample keys + | - Format: "123s" (fixed), "range 60s to 3600s (avg 1800s)" (variable), "no expiry" (persistent) |- Total key count across all namespaces |- Redis availability status | @@ -755,7 +752,8 @@ trait APIMethods600 { key_count = 42, description = "Rate limit call counters", category = "Rate Limiting", - storage_location = "redis" + storage_location = "redis", + ttl_info = "range 60s to 86400s (avg 3600s)" ), CacheNamespaceInfoJsonV600( namespace_id = "rd_localised", @@ -764,7 +762,8 @@ trait APIMethods600 { key_count = 128, description = "Localized resource docs", category = "API Documentation", - storage_location = "redis" + storage_location = "redis", + ttl_info = "3600s" ) ), total_keys = 170, diff --git a/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala b/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala index 2a29d7a96..36ab2d96b 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala @@ -268,16 +268,21 @@ case class InvalidatedCacheNamespaceJsonV600( status: String ) -case class CacheProviderConfigJsonV600( - provider: String, - enabled: Boolean, - url: Option[String], - port: Option[Int], - use_ssl: Option[Boolean] +case class RedisCacheStatusJsonV600( + available: Boolean, + url: String, + port: Int, + use_ssl: Boolean +) + +case class InMemoryCacheStatusJsonV600( + available: Boolean, + current_size: Long ) case class CacheConfigJsonV600( - providers: List[CacheProviderConfigJsonV600], + redis_status: RedisCacheStatusJsonV600, + in_memory_status: InMemoryCacheStatusJsonV600, instance_id: String, environment: String, global_prefix: String @@ -290,7 +295,8 @@ case class CacheNamespaceInfoJsonV600( key_count: Int, description: String, category: String, - storage_location: String + storage_location: String, + ttl_info: String ) case class CacheInfoJsonV600( @@ -1120,21 +1126,17 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { import code.api.Constant import net.liftweb.util.Props - val redisProvider = CacheProviderConfigJsonV600( - provider = "redis", - enabled = true, - url = Some(Redis.url), - port = Some(Redis.port), - use_ssl = Some(Redis.useSsl) - ) + val redisIsReady = try { + Redis.isRedisReady + } catch { + case _: Throwable => false + } - val inMemoryProvider = CacheProviderConfigJsonV600( - provider = "in_memory", - enabled = true, - url = None, - port = None, - use_ssl = None - ) + val inMemorySize = try { + InMemory.underlyingGuavaCache.size() + } catch { + case _: Throwable => 0L + } val instanceId = code.api.util.APIUtil.getPropsValue("api_instance_id").getOrElse("obp") val environment = Props.mode match { @@ -1145,8 +1147,21 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { case _ => "unknown" } + val redisStatus = RedisCacheStatusJsonV600( + available = redisIsReady, + url = Redis.url, + port = Redis.port, + use_ssl = Redis.useSsl + ) + + val inMemoryStatus = InMemoryCacheStatusJsonV600( + available = inMemorySize >= 0, + current_size = inMemorySize + ) + CacheConfigJsonV600( - providers = List(redisProvider, inMemoryProvider), + redis_status = redisStatus, + in_memory_status = inMemoryStatus, instance_id = instanceId, environment = environment, global_prefix = Constant.getGlobalCacheNamespacePrefix @@ -1156,6 +1171,7 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { def createCacheInfoJsonV600(): CacheInfoJsonV600 = { import code.api.cache.{Redis, InMemory} import code.api.Constant + import code.api.JedisMethod val namespaceDescriptions = Map( Constant.CALL_COUNTER_NAMESPACE -> ("Rate limit call counters", "Rate Limiting"), @@ -1183,10 +1199,33 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { var redisKeyCount = 0 var memoryKeyCount = 0 var storageLocation = "unknown" + var ttlInfo = "no keys to sample" try { redisKeyCount = Redis.countKeys(pattern) totalKeys += redisKeyCount + + // Sample keys to get TTL information + if (redisKeyCount > 0) { + val sampleKeys = Redis.scanKeys(pattern).take(5) + val ttls = sampleKeys.flatMap { key => + Redis.use(JedisMethod.TTL, key, None, None).map(_.toLong) + } + + if (ttls.nonEmpty) { + val minTtl = ttls.min + val maxTtl = ttls.max + val avgTtl = ttls.sum / ttls.length.toLong + + ttlInfo = if (minTtl == maxTtl) { + if (minTtl == -1) "no expiry" + else if (minTtl == -2) "keys expired or missing" + else s"${minTtl}s" + } else { + s"range ${minTtl}s to ${maxTtl}s (avg ${avgTtl}s)" + } + } + } } catch { case _: Throwable => redisAvailable = false @@ -1195,6 +1234,10 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { try { memoryKeyCount = InMemory.countKeys(pattern) totalKeys += memoryKeyCount + + if (memoryKeyCount > 0 && redisKeyCount == 0) { + ttlInfo = "in-memory (no TTL in Guava cache)" + } } catch { case _: Throwable => // In-memory cache error (shouldn't happen, but handle gracefully) @@ -1203,6 +1246,7 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { // Determine storage based on where keys actually exist val keyCount = if (redisKeyCount > 0 && memoryKeyCount > 0) { storageLocation = "both" + ttlInfo = s"redis: ${ttlInfo}, memory: in-memory cache" redisKeyCount + memoryKeyCount } else if (redisKeyCount > 0) { storageLocation = "redis" @@ -1225,7 +1269,8 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { key_count = keyCount, description = description, category = category, - storage_location = storageLocation + storage_location = storageLocation, + ttl_info = ttlInfo ) } diff --git a/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala index ee8460f73..0b181a03f 100644 --- a/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala +++ b/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala @@ -158,6 +158,8 @@ class CacheEndpointsTest extends V600ServerSetup { namespace.category should not be empty namespace.storage_location should not be empty namespace.storage_location should (equal("redis") or equal("memory") or equal("both") or equal("unknown")) + namespace.ttl_info should not be empty + namespace.ttl_info shouldBe a[String] } } } From 63194b3ead2c4d2e57234e16a31014694c72111c Mon Sep 17 00:00:00 2001 From: simonredfern Date: Thu, 1 Jan 2026 04:36:28 +0100 Subject: [PATCH 11/48] System Cache Config fields fix --- obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 69190fb78..3f8a0d05e 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -27,7 +27,7 @@ import code.api.v5_0_0.{ViewJsonV500, ViewsJsonV500} import code.api.v5_1_0.{JSONFactory510, PostCustomerLegalNameJsonV510} import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo} import code.api.v6_0_0.JSONFactory600.{AddUserToGroupResponseJsonV600, DynamicEntityDiagnosticsJsonV600, DynamicEntityIssueJsonV600, GroupEntitlementJsonV600, GroupEntitlementsJsonV600, GroupJsonV600, GroupsJsonV600, PostGroupJsonV600, PostGroupMembershipJsonV600, PostResetPasswordUrlJsonV600, PutGroupJsonV600, ReferenceTypeJsonV600, ReferenceTypesJsonV600, ResetPasswordUrlJsonV600, RoleWithEntitlementCountJsonV600, RolesWithEntitlementCountsJsonV600, ScannedApiVersionJsonV600, UpdateViewJsonV600, UserGroupMembershipJsonV600, UserGroupMembershipsJsonV600, ValidateUserEmailJsonV600, ValidateUserEmailResponseJsonV600, ViewJsonV600, ViewPermissionJsonV600, ViewPermissionsJsonV600, ViewsJsonV600, createAbacRuleJsonV600, createAbacRulesJsonV600, createActiveRateLimitsJsonV600, createCallLimitJsonV600, createRedisCallCountersJson} -import code.api.v6_0_0.{AbacRuleJsonV600, AbacRuleResultJsonV600, AbacRulesJsonV600, CacheConfigJsonV600, CacheInfoJsonV600, CacheNamespaceInfoJsonV600, CacheProviderConfigJsonV600, CreateAbacRuleJsonV600, CurrentConsumerJsonV600, ExecuteAbacRuleJsonV600, UpdateAbacRuleJsonV600} +import code.api.v6_0_0.{AbacRuleJsonV600, AbacRuleResultJsonV600, AbacRulesJsonV600, CacheConfigJsonV600, CacheInfoJsonV600, CacheNamespaceInfoJsonV600, CreateAbacRuleJsonV600, CurrentConsumerJsonV600, ExecuteAbacRuleJsonV600, InMemoryCacheStatusJsonV600, RedisCacheStatusJsonV600, UpdateAbacRuleJsonV600} import code.api.v6_0_0.OBPAPI6_0_0 import code.abacrule.{AbacRuleEngine, MappedAbacRuleProvider} import code.metrics.APIMetrics From 848dee52b86a625513eae212a3017c4b5b1e5a64 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Thu, 1 Jan 2026 04:40:39 +0100 Subject: [PATCH 12/48] System Cache Config fields fix tests --- .../code/api/v6_0_0/CacheEndpointsTest.scala | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala index 0b181a03f..7dd6022da 100644 --- a/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala +++ b/obp-api/src/test/scala/code/api/v6_0_0/CacheEndpointsTest.scala @@ -90,16 +90,19 @@ class CacheEndpointsTest extends V600ServerSetup { And("The response should have the correct structure") val cacheConfig = response.body.extract[CacheConfigJsonV600] - cacheConfig.providers should not be empty cacheConfig.instance_id should not be empty cacheConfig.environment should not be empty cacheConfig.global_prefix should not be empty - And("Providers should have valid data") - cacheConfig.providers.foreach { provider => - provider.provider should not be empty - provider.enabled shouldBe a[Boolean] - } + And("Redis status should have valid data") + cacheConfig.redis_status.available shouldBe a[Boolean] + cacheConfig.redis_status.url should not be empty + cacheConfig.redis_status.port should be > 0 + cacheConfig.redis_status.use_ssl shouldBe a[Boolean] + + And("In-memory status should have valid data") + cacheConfig.in_memory_status.available shouldBe a[Boolean] + cacheConfig.in_memory_status.current_size should be >= 0L } } From 57ea96d6bb3185f17ea72a82752d112d7774fc77 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Sun, 4 Jan 2026 20:23:19 +0100 Subject: [PATCH 13/48] bugfix: support multiple oauth2.jwk_set.url --- obp-api/src/main/scala/code/api/OAuth2.scala | 106 +++++++++++------- .../scala/code/api/util/ErrorMessages.scala | 2 +- 2 files changed, 68 insertions(+), 40 deletions(-) diff --git a/obp-api/src/main/scala/code/api/OAuth2.scala b/obp-api/src/main/scala/code/api/OAuth2.scala index 00800f99f..9ba607c7b 100644 --- a/obp-api/src/main/scala/code/api/OAuth2.scala +++ b/obp-api/src/main/scala/code/api/OAuth2.scala @@ -228,6 +228,71 @@ object OAuth2Login extends RestHelper with MdcLoggable { def urlOfJwkSets: Box[String] = Constant.oauth2JwkSetUrl + /** + * Get all JWKS URLs from configuration. + * This is a helper method for trying multiple JWKS URLs when validating tokens. + * We need more than one JWKS URL if we have multiple OIDC providers configured etc. + * @return List of all configured JWKS URLs + */ + protected def getAllJwksUrls: List[String] = { + val url: List[String] = Constant.oauth2JwkSetUrl.toList + url.flatMap(_.split(",").toList).map(_.trim).filter(_.nonEmpty) + } + + /** + * Try to validate a JWT token with multiple JWKS URLs. + * This is a generic retry mechanism that works for both ID tokens and access tokens. + * + * @param token The JWT token to validate + * @param tokenType Description of token type for logging (e.g., "ID token", "access token") + * @param validateFunc Function that validates token against a JWKS URL + * @tparam T The type of claims returned (IDTokenClaimsSet or JWTClaimsSet) + * @return Boxed claims or failure + */ + protected def tryValidateWithAllJwksUrls[T]( + token: String, + tokenType: String, + validateFunc: (String, String) => Box[T] + ): Box[T] = { + logger.debug(s"tryValidateWithAllJwksUrls - attempting to validate $tokenType") + + // Extract issuer for better error reporting + val actualIssuer = JwtUtil.getIssuer(token).getOrElse("NO_ISSUER_CLAIM") + logger.debug(s"tryValidateWithAllJwksUrls - JWT issuer claim: '$actualIssuer'") + + // Get all JWKS URLs + val allJwksUrls = getAllJwksUrls + + if (allJwksUrls.isEmpty) { + logger.debug(s"tryValidateWithAllJwksUrls - No JWKS URLs configured") + return Failure(Oauth2ThereIsNoUrlOfJwkSet) + } + + logger.debug(s"tryValidateWithAllJwksUrls - Will try ${allJwksUrls.size} JWKS URL(s): $allJwksUrls") + + // Try each JWKS URL until one succeeds + val results = allJwksUrls.map { url => + logger.debug(s"tryValidateWithAllJwksUrls - Trying JWKS URL: '$url'") + val result = validateFunc(token, url) + result match { + case Full(_) => + logger.debug(s"tryValidateWithAllJwksUrls - SUCCESS with JWKS URL: '$url'") + case Failure(msg, _, _) => + logger.debug(s"tryValidateWithAllJwksUrls - FAILED with JWKS URL: '$url', reason: $msg") + case _ => + logger.debug(s"tryValidateWithAllJwksUrls - FAILED with JWKS URL: '$url'") + } + result + } + + // Return the first successful result, or the last failure + results.find(_.isDefined).getOrElse { + logger.debug(s"tryValidateWithAllJwksUrls - All ${allJwksUrls.size} JWKS URL(s) failed for issuer: '$actualIssuer'") + logger.debug(s"tryValidateWithAllJwksUrls - Tried URLs: $allJwksUrls") + results.lastOption.getOrElse(Failure(Oauth2ThereIsNoUrlOfJwkSet)) + } + } + def checkUrlOfJwkSets(identityProvider: String) = { val url: List[String] = Constant.oauth2JwkSetUrl.toList val jwksUris: List[String] = url.map(_.toLowerCase()).map(_.split(",").toList).flatten @@ -310,47 +375,10 @@ object OAuth2Login extends RestHelper with MdcLoggable { }.getOrElse(false) } def validateIdToken(idToken: String): Box[IDTokenClaimsSet] = { - logger.debug(s"validateIdToken - attempting to validate ID token") - - // Extract issuer for better error reporting - val actualIssuer = JwtUtil.getIssuer(idToken).getOrElse("NO_ISSUER_CLAIM") - logger.debug(s"validateIdToken - JWT issuer claim: '$actualIssuer'") - - urlOfJwkSets match { - case Full(url) => - logger.debug(s"validateIdToken - using JWKS URL: '$url'") - JwtUtil.validateIdToken(idToken, url) - case ParamFailure(a, b, c, apiFailure : APIFailure) => - logger.debug(s"validateIdToken - ParamFailure: $a, $b, $c, $apiFailure") - logger.debug(s"validateIdToken - JWT issuer was: '$actualIssuer'") - ParamFailure(a, b, c, apiFailure : APIFailure) - case Failure(msg, t, c) => - logger.debug(s"validateIdToken - Failure getting JWKS URL: $msg") - logger.debug(s"validateIdToken - JWT issuer was: '$actualIssuer'") - if (msg.contains("OBP-20208")) { - logger.debug("validateIdToken - OBP-20208 Error Details:") - logger.debug(s"validateIdToken - JWT issuer claim: '$actualIssuer'") - logger.debug(s"validateIdToken - oauth2.jwk_set.url value: '${Constant.oauth2JwkSetUrl}'") - logger.debug("validateIdToken - Check that the JWKS URL configuration matches the JWT issuer") - } - Failure(msg, t, c) - case _ => - logger.debug("validateIdToken - No JWKS URL available") - logger.debug(s"validateIdToken - JWT issuer was: '$actualIssuer'") - Failure(Oauth2ThereIsNoUrlOfJwkSet) - } + tryValidateWithAllJwksUrls(idToken, "ID token", JwtUtil.validateIdToken) } def validateAccessToken(accessToken: String): Box[JWTClaimsSet] = { - urlOfJwkSets match { - case Full(url) => - JwtUtil.validateAccessToken(accessToken, url) - case ParamFailure(a, b, c, apiFailure : APIFailure) => - ParamFailure(a, b, c, apiFailure : APIFailure) - case Failure(msg, t, c) => - Failure(msg, t, c) - case _ => - Failure(Oauth2ThereIsNoUrlOfJwkSet) - } + tryValidateWithAllJwksUrls(accessToken, "access token", JwtUtil.validateAccessToken) } /** New Style Endpoints * This function creates user based on "iss" and "sub" fields diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index acaad26de..4c17086c1 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -269,7 +269,7 @@ object ErrorMessages { val Oauth2ThereIsNoUrlOfJwkSet = "OBP-20203: There is no an URL of OAuth 2.0 server's JWK set, published at a well-known URL." val Oauth2BadJWTException = "OBP-20204: Bad JWT error. " val Oauth2ParseException = "OBP-20205: Parse error. " - val Oauth2BadJOSEException = "OBP-20206: Bad JSON Object Signing and Encryption (JOSE) exception. The ID token is invalid or expired. " + val Oauth2BadJOSEException = "OBP-20206: Bad JSON Object Signing and Encryption (JOSE) exception. The ID token is invalid or expired. OBP-API Admin should check the oauth2.jwk_set.url list contains the jwks url of the provider." 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. " From 060d9beeeed9f8257940323b53d209f75fb6a370 Mon Sep 17 00:00:00 2001 From: tesobe-daniel Date: Mon, 5 Jan 2026 13:35:10 +0100 Subject: [PATCH 14/48] Ignore GitHub directory in .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d990d9c46..b52072215 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.github/* *.class *.db .DS_Store From 69cc8c008a92ed13302025cf459e44fc8318383b Mon Sep 17 00:00:00 2001 From: simonredfern Date: Mon, 5 Jan 2026 17:40:54 +0100 Subject: [PATCH 15/48] Resource doc yaml respects content parameter --- .../api/ResourceDocs1_4_0/ResourceDocs140.scala | 15 ++++++++++----- .../ResourceDocsAPIMethods.scala | 6 +++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala index 3845c33ea..70f4b4cd5 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocs140.scala @@ -208,11 +208,16 @@ object ResourceDocs300 extends OBPRestHelper with ResourceDocsAPIMethods with Md val resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(resourceDocs, isVersion4OrHigher, locale) resourceDocsJson.resource_docs case _ => - // Get all resource docs for the requested version - val allResourceDocs = ImplementationsResourceDocs.getResourceDocsList(requestedApiVersion).getOrElse(List.empty) - val filteredResourceDocs = ResourceDocsAPIMethodsUtil.filterResourceDocs(allResourceDocs, resourceDocTags, partialFunctions) - val resourceDocJson = JSONFactory1_4_0.createResourceDocsJson(filteredResourceDocs, isVersion4OrHigher, locale) - resourceDocJson.resource_docs + contentParam match { + case Some(DYNAMIC) => + ImplementationsResourceDocs.getResourceDocsObpDynamicCached(resourceDocTags, partialFunctions, locale, None, isVersion4OrHigher).head.resource_docs + case Some(STATIC) => { + ImplementationsResourceDocs.getStaticResourceDocsObpCached(requestedApiVersionString, resourceDocTags, partialFunctions, locale, isVersion4OrHigher).head.resource_docs + } + case _ => { + ImplementationsResourceDocs.getAllResourceDocsObpCached(requestedApiVersionString, resourceDocTags, partialFunctions, locale, contentParam, isVersion4OrHigher).head.resource_docs + } + } } val hostname = HostName diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index 9966ee298..fc6c5995e 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -225,7 +225,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth * @param contentParam if this is Some(`true`), only show dynamic endpoints, if Some(`false`), only show static. If it is None, we will show all. default is None * @return */ - private def getStaticResourceDocsObpCached( + def getStaticResourceDocsObpCached( requestedApiVersionString: String, resourceDocTags: Option[List[ResourceDocTag]], partialFunctionNames: Option[List[String]], @@ -245,7 +245,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth * @param contentParam if this is Some(`true`), only show dynamic endpoints, if Some(`false`), only show static. If it is None, we will show all. default is None * @return */ - private def getAllResourceDocsObpCached( + def getAllResourceDocsObpCached( requestedApiVersionString: String, resourceDocTags: Option[List[ResourceDocTag]], partialFunctionNames: Option[List[String]], @@ -288,7 +288,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } - private def getResourceDocsObpDynamicCached( + def getResourceDocsObpDynamicCached( resourceDocTags: Option[List[ResourceDocTag]], partialFunctionNames: Option[List[String]], locale: Option[String], From b7b240c92229cac16c282e14314378a92872af4e Mon Sep 17 00:00:00 2001 From: simonredfern Date: Mon, 5 Jan 2026 23:47:21 +0100 Subject: [PATCH 16/48] Log cache separate endpoints and different Role names --- .../scala/code/api/cache/RedisLogger.scala | 12 +- .../main/scala/code/api/util/ApiRole.scala | 36 +-- .../scala/code/api/v5_1_0/APIMethods510.scala | 213 +++++++++++++++--- .../api/v5_1_0/LogCacheEndpointTest.scala | 74 +++--- 4 files changed, 236 insertions(+), 99 deletions(-) diff --git a/obp-api/src/main/scala/code/api/cache/RedisLogger.scala b/obp-api/src/main/scala/code/api/cache/RedisLogger.scala index ee9b58c3a..02db0209c 100644 --- a/obp-api/src/main/scala/code/api/cache/RedisLogger.scala +++ b/obp-api/src/main/scala/code/api/cache/RedisLogger.scala @@ -73,12 +73,12 @@ object RedisLogger { /** Map a LogLevel to its required entitlements */ def requiredRoles(level: LogLevel): List[ApiRole] = level match { - case TRACE => List(canGetTraceLevelLogsAtAllBanks, canGetAllLevelLogsAtAllBanks) - case DEBUG => List(canGetDebugLevelLogsAtAllBanks, canGetAllLevelLogsAtAllBanks) - case INFO => List(canGetInfoLevelLogsAtAllBanks, canGetAllLevelLogsAtAllBanks) - case WARNING => List(canGetWarningLevelLogsAtAllBanks, canGetAllLevelLogsAtAllBanks) - case ERROR => List(canGetErrorLevelLogsAtAllBanks, canGetAllLevelLogsAtAllBanks) - case ALL => List(canGetAllLevelLogsAtAllBanks) + case TRACE => List(canGetSystemLogCacheTrace, canGetSystemLogCacheAll) + case DEBUG => List(canGetSystemLogCacheDebug, canGetSystemLogCacheAll) + case INFO => List(canGetSystemLogCacheInfo, canGetSystemLogCacheAll) + case WARNING => List(canGetSystemLogCacheWarning, canGetSystemLogCacheAll) + case ERROR => List(canGetSystemLogCacheError, canGetSystemLogCacheAll) + case ALL => List(canGetSystemLogCacheAll) } } diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index c025fe7c2..9c7a990be 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -107,35 +107,23 @@ object ApiRole extends MdcLoggable{ // TRACE - case class CanGetTraceLevelLogsAtOneBank(requiresBankId: Boolean = true) extends ApiRole - lazy val canGetTraceLevelLogsAtOneBank = CanGetTraceLevelLogsAtOneBank() - case class CanGetTraceLevelLogsAtAllBanks(requiresBankId: Boolean = false) extends ApiRole - lazy val canGetTraceLevelLogsAtAllBanks = CanGetTraceLevelLogsAtAllBanks() + case class CanGetSystemLogCacheTrace(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetSystemLogCacheTrace = CanGetSystemLogCacheTrace() // DEBUG - case class CanGetDebugLevelLogsAtOneBank(requiresBankId: Boolean = true) extends ApiRole - lazy val canGetDebugLevelLogsAtOneBank = CanGetDebugLevelLogsAtOneBank() - case class CanGetDebugLevelLogsAtAllBanks(requiresBankId: Boolean = false) extends ApiRole - lazy val canGetDebugLevelLogsAtAllBanks = CanGetDebugLevelLogsAtAllBanks() + case class CanGetSystemLogCacheDebug(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetSystemLogCacheDebug = CanGetSystemLogCacheDebug() // INFO - case class CanGetInfoLevelLogsAtOneBank(requiresBankId: Boolean = true) extends ApiRole - lazy val canGetInfoLevelLogsAtOneBank = CanGetInfoLevelLogsAtOneBank() - case class CanGetInfoLevelLogsAtAllBanks(requiresBankId: Boolean = false) extends ApiRole - lazy val canGetInfoLevelLogsAtAllBanks = CanGetInfoLevelLogsAtAllBanks() + case class CanGetSystemLogCacheInfo(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetSystemLogCacheInfo = CanGetSystemLogCacheInfo() // WARNING - case class CanGetWarningLevelLogsAtOneBank(requiresBankId: Boolean = true) extends ApiRole - lazy val canGetWarningLevelLogsAtOneBank = CanGetWarningLevelLogsAtOneBank() - case class CanGetWarningLevelLogsAtAllBanks(requiresBankId: Boolean = false) extends ApiRole - lazy val canGetWarningLevelLogsAtAllBanks = CanGetWarningLevelLogsAtAllBanks() + case class CanGetSystemLogCacheWarning(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetSystemLogCacheWarning = CanGetSystemLogCacheWarning() // ERROR - case class CanGetErrorLevelLogsAtOneBank(requiresBankId: Boolean = true) extends ApiRole - lazy val canGetErrorLevelLogsAtOneBank = CanGetErrorLevelLogsAtOneBank() - case class CanGetErrorLevelLogsAtAllBanks(requiresBankId: Boolean = false) extends ApiRole - lazy val canGetErrorLevelLogsAtAllBanks = CanGetErrorLevelLogsAtAllBanks() + case class CanGetSystemLogCacheError(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetSystemLogCacheError = CanGetSystemLogCacheError() // ALL - case class CanGetAllLevelLogsAtOneBank(requiresBankId: Boolean = true) extends ApiRole - lazy val canGetAllLevelLogsAtOneBank = CanGetAllLevelLogsAtOneBank() - case class CanGetAllLevelLogsAtAllBanks(requiresBankId: Boolean = false) extends ApiRole - lazy val canGetAllLevelLogsAtAllBanks = CanGetAllLevelLogsAtAllBanks() + case class CanGetSystemLogCacheAll(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetSystemLogCacheAll = CanGetSystemLogCacheAll() case class CanUpdateAgentStatusAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canUpdateAgentStatusAtAnyBank = CanUpdateAgentStatusAtAnyBank() diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 7357f474f..8f8968e45 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -238,55 +238,204 @@ trait APIMethods510 { } } + // Helper function to avoid code duplication + private def getLogCacheHelper(level: RedisLogger.LogLevel.Value, cc: CallContext): Future[(RedisLogger.LogTail, Option[CallContext])] = { + implicit val ec = EndpointContext(Some(cc)) + for { + httpParams <- NewStyle.function.extractHttpParamsFromUrl(cc.url) + (obpQueryParams, callContext) <- createQueriesByHttpParamsFuture(httpParams, cc.callContext) + limit = obpQueryParams.collectFirst { case OBPLimit(value) => value } + offset = obpQueryParams.collectFirst { case OBPOffset(value) => value } + logs <- Future(RedisLogger.getLogTail(level, limit, offset)) + } yield { + (logs, HttpCode.`200`(callContext)) + } + } + staticResourceDocs += ResourceDoc( - logCacheEndpoint, + logCacheTraceEndpoint, implementedInApiVersion, - nameOf(logCacheEndpoint), + nameOf(logCacheTraceEndpoint), "GET", - "/system/log-cache/LOG_LEVEL", - "Get Log Cache", - """Returns information about: - | - |* Log Cache + "/system/log-cache/trace", + "Get Trace Level Log Cache", + """Returns TRACE level logs from the system log cache. | |This endpoint supports pagination via the following optional query parameters: |* limit - Maximum number of log entries to return |* offset - Number of log entries to skip (for pagination) | - |Example: GET /system/log-cache/INFO?limit=50&offset=100 + |Example: GET /system/log-cache/trace?limit=50&offset=100 """, EmptyBody, EmptyBody, List($UserNotLoggedIn, UnknownError), apiTagSystem :: apiTagApi :: Nil, - Some(List(canGetAllLevelLogsAtAllBanks))) + Some(List(canGetSystemLogCacheTrace, canGetSystemLogCacheAll))) - lazy val logCacheEndpoint: OBPEndpoint = { - case "system" :: "log-cache" :: logLevel :: Nil JsonGet _ => + lazy val logCacheTraceEndpoint: OBPEndpoint = { + case "system" :: "log-cache" :: "trace" :: Nil JsonGet _ => cc => implicit val ec = EndpointContext(Some(cc)) for { - // Parse and validate log level - level <- NewStyle.function.tryons(ErrorMessages.invalidLogLevel, 400, cc.callContext) { - RedisLogger.LogLevel.valueOf(logLevel) - } - // Check entitlements using helper - _ <- NewStyle.function.handleEntitlementsAndScopes( - bankId = "", - userId = cc.userId, - roles = RedisLogger.LogLevel.requiredRoles(level), - callContext = cc.callContext - ) - httpParams <- NewStyle.function.extractHttpParamsFromUrl(cc.url) - (obpQueryParams, callContext) <- createQueriesByHttpParamsFuture(httpParams, cc.callContext) - // Extract limit and offset from query parameters - limit = obpQueryParams.collectFirst { case OBPLimit(value) => value } - offset = obpQueryParams.collectFirst { case OBPOffset(value) => value } - // Fetch logs with pagination - logs <- Future(RedisLogger.getLogTail(level, limit, offset)) - } yield { - (logs, HttpCode.`200`(cc.callContext)) - } + _ <- NewStyle.function.handleEntitlementsAndScopes("", cc.userId, List(canGetSystemLogCacheTrace, canGetSystemLogCacheAll), cc.callContext) + result <- getLogCacheHelper(RedisLogger.LogLevel.TRACE, cc) + } yield result + } + + staticResourceDocs += ResourceDoc( + logCacheDebugEndpoint, + implementedInApiVersion, + nameOf(logCacheDebugEndpoint), + "GET", + "/system/log-cache/debug", + "Get Debug Level Log Cache", + """Returns DEBUG level logs from the system log cache. + | + |This endpoint supports pagination via the following optional query parameters: + |* limit - Maximum number of log entries to return + |* offset - Number of log entries to skip (for pagination) + | + |Example: GET /system/log-cache/debug?limit=50&offset=100 + """, + EmptyBody, + EmptyBody, + List($UserNotLoggedIn, UnknownError), + apiTagSystem :: apiTagApi :: Nil, + Some(List(canGetSystemLogCacheDebug, canGetSystemLogCacheAll))) + + lazy val logCacheDebugEndpoint: OBPEndpoint = { + case "system" :: "log-cache" :: "debug" :: Nil JsonGet _ => + cc => + implicit val ec = EndpointContext(Some(cc)) + for { + _ <- NewStyle.function.handleEntitlementsAndScopes("", cc.userId, List(canGetSystemLogCacheDebug, canGetSystemLogCacheAll), cc.callContext) + result <- getLogCacheHelper(RedisLogger.LogLevel.DEBUG, cc) + } yield result + } + + staticResourceDocs += ResourceDoc( + logCacheInfoEndpoint, + implementedInApiVersion, + nameOf(logCacheInfoEndpoint), + "GET", + "/system/log-cache/info", + "Get Info Level Log Cache", + """Returns INFO level logs from the system log cache. + | + |This endpoint supports pagination via the following optional query parameters: + |* limit - Maximum number of log entries to return + |* offset - Number of log entries to skip (for pagination) + | + |Example: GET /system/log-cache/info?limit=50&offset=100 + """, + EmptyBody, + EmptyBody, + List($UserNotLoggedIn, UnknownError), + apiTagSystem :: apiTagApi :: Nil, + Some(List(canGetSystemLogCacheInfo, canGetSystemLogCacheAll))) + + lazy val logCacheInfoEndpoint: OBPEndpoint = { + case "system" :: "log-cache" :: "info" :: Nil JsonGet _ => + cc => + implicit val ec = EndpointContext(Some(cc)) + for { + _ <- NewStyle.function.handleEntitlementsAndScopes("", cc.userId, List(canGetSystemLogCacheInfo, canGetSystemLogCacheAll), cc.callContext) + result <- getLogCacheHelper(RedisLogger.LogLevel.INFO, cc) + } yield result + } + + staticResourceDocs += ResourceDoc( + logCacheWarningEndpoint, + implementedInApiVersion, + nameOf(logCacheWarningEndpoint), + "GET", + "/system/log-cache/warning", + "Get Warning Level Log Cache", + """Returns WARNING level logs from the system log cache. + | + |This endpoint supports pagination via the following optional query parameters: + |* limit - Maximum number of log entries to return + |* offset - Number of log entries to skip (for pagination) + | + |Example: GET /system/log-cache/warning?limit=50&offset=100 + """, + EmptyBody, + EmptyBody, + List($UserNotLoggedIn, UnknownError), + apiTagSystem :: apiTagApi :: Nil, + Some(List(canGetSystemLogCacheWarning, canGetSystemLogCacheAll))) + + lazy val logCacheWarningEndpoint: OBPEndpoint = { + case "system" :: "log-cache" :: "warning" :: Nil JsonGet _ => + cc => + implicit val ec = EndpointContext(Some(cc)) + for { + _ <- NewStyle.function.handleEntitlementsAndScopes("", cc.userId, List(canGetSystemLogCacheWarning, canGetSystemLogCacheAll), cc.callContext) + result <- getLogCacheHelper(RedisLogger.LogLevel.WARNING, cc) + } yield result + } + + staticResourceDocs += ResourceDoc( + logCacheErrorEndpoint, + implementedInApiVersion, + nameOf(logCacheErrorEndpoint), + "GET", + "/system/log-cache/error", + "Get Error Level Log Cache", + """Returns ERROR level logs from the system log cache. + | + |This endpoint supports pagination via the following optional query parameters: + |* limit - Maximum number of log entries to return + |* offset - Number of log entries to skip (for pagination) + | + |Example: GET /system/log-cache/error?limit=50&offset=100 + """, + EmptyBody, + EmptyBody, + List($UserNotLoggedIn, UnknownError), + apiTagSystem :: apiTagApi :: Nil, + Some(List(canGetSystemLogCacheError, canGetSystemLogCacheAll))) + + lazy val logCacheErrorEndpoint: OBPEndpoint = { + case "system" :: "log-cache" :: "error" :: Nil JsonGet _ => + cc => + implicit val ec = EndpointContext(Some(cc)) + for { + _ <- NewStyle.function.handleEntitlementsAndScopes("", cc.userId, List(canGetSystemLogCacheError, canGetSystemLogCacheAll), cc.callContext) + result <- getLogCacheHelper(RedisLogger.LogLevel.ERROR, cc) + } yield result + } + + staticResourceDocs += ResourceDoc( + logCacheAllEndpoint, + implementedInApiVersion, + nameOf(logCacheAllEndpoint), + "GET", + "/system/log-cache/all", + "Get All Level Log Cache", + """Returns logs of all levels from the system log cache. + | + |This endpoint supports pagination via the following optional query parameters: + |* limit - Maximum number of log entries to return + |* offset - Number of log entries to skip (for pagination) + | + |Example: GET /system/log-cache/all?limit=50&offset=100 + """, + EmptyBody, + EmptyBody, + List($UserNotLoggedIn, UnknownError), + apiTagSystem :: apiTagApi :: Nil, + Some(List(canGetSystemLogCacheAll))) + + lazy val logCacheAllEndpoint: OBPEndpoint = { + case "system" :: "log-cache" :: "all" :: Nil JsonGet _ => + cc => + implicit val ec = EndpointContext(Some(cc)) + for { + _ <- NewStyle.function.handleEntitlementsAndScopes("", cc.userId, List(canGetSystemLogCacheAll), cc.callContext) + result <- getLogCacheHelper(RedisLogger.LogLevel.ALL, cc) + } yield result } diff --git a/obp-api/src/test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala index 70f1a8e56..690464e06 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala @@ -1,7 +1,7 @@ package code.api.v5_1_0 import code.api.util.APIUtil.OAuth._ -import code.api.util.ApiRole.CanGetAllLevelLogsAtAllBanks +import code.api.util.ApiRole.CanGetSystemLogCacheAll import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 import code.entitlement.Entitlement @@ -21,12 +21,12 @@ class LogCacheEndpointTest extends V510ServerSetup { * This is made possible by the scalatest maven plugin */ object VersionOfApi extends Tag(ApiVersion.v5_1_0.toString) - object ApiEndpoint1 extends Tag(nameOf(Implementations5_1_0.logCacheEndpoint)) + object ApiEndpoint1 extends Tag(nameOf(Implementations5_1_0.logCacheInfoEndpoint)) feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") { scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) { When("We make a request v5.1.0") - val request = (v5_1_0_Request / "system" / "log-cache" / "INFO").GET + val request = (v5_1_0_Request / "system" / "log-cache" / "info").GET val response = makeGetRequest(request) Then("We should get a 401") response.code should equal(401) @@ -37,21 +37,21 @@ class LogCacheEndpointTest extends V510ServerSetup { feature(s"test $ApiEndpoint1 version $VersionOfApi - Missing entitlement") { scenario("We will call the endpoint with user credentials but without proper entitlement", ApiEndpoint1, VersionOfApi) { When("We make a request v5.1.0") - val request = (v5_1_0_Request / "system" / "log-cache" / "INFO").GET <@(user1) + val request = (v5_1_0_Request / "system" / "log-cache" / "info").GET <@(user1) val response = makeGetRequest(request) - Then("error should be " + UserHasMissingRoles + CanGetAllLevelLogsAtAllBanks) + Then("error should be " + UserHasMissingRoles + CanGetSystemLogCacheAll) response.code should equal(403) - response.body.extract[ErrorMessage].message should be(UserHasMissingRoles + CanGetAllLevelLogsAtAllBanks) + response.body.extract[ErrorMessage].message should be(UserHasMissingRoles + CanGetSystemLogCacheAll) } } feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access without pagination") { scenario("We get log cache without pagination parameters", ApiEndpoint1, VersionOfApi) { Given("We have a user with proper entitlement") - Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAllLevelLogsAtAllBanks.toString) + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetSystemLogCacheAll.toString) When("We make a request to get log cache") - val request = (v5_1_0_Request / "system" / "log-cache" / "INFO").GET <@(user1) + val request = (v5_1_0_Request / "system" / "log-cache" / "info").GET <@(user1) val response = makeGetRequest(request) Then("We should get a successful response") @@ -66,10 +66,10 @@ class LogCacheEndpointTest extends V510ServerSetup { feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access with limit parameter") { scenario("We get log cache with limit parameter only", ApiEndpoint1, VersionOfApi) { Given("We have a user with proper entitlement") - Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetAllLevelLogsAtAllBanks.toString) + Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetSystemLogCacheAll.toString) When("We make a request with limit parameter") - val request = (v5_1_0_Request / "system" / "log-cache" / "INFO").GET <@(user1) < val request = (v5_1_0_Request / "system" / "log-cache" / logLevel).GET <@(user1) < Date: Mon, 5 Jan 2026 23:49:39 +0100 Subject: [PATCH 17/48] Add apiTagLogCache tag to log cache endpoints --- obp-api/src/main/scala/code/api/util/ApiTag.scala | 1 + .../main/scala/code/api/v5_1_0/APIMethods510.scala | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiTag.scala b/obp-api/src/main/scala/code/api/util/ApiTag.scala index 91b4f3eb9..bd4c41f01 100644 --- a/obp-api/src/main/scala/code/api/util/ApiTag.scala +++ b/obp-api/src/main/scala/code/api/util/ApiTag.scala @@ -91,6 +91,7 @@ object ApiTag { val apiTagDevOps = ResourceDocTag("DevOps") val apiTagSystem = ResourceDocTag("System") val apiTagCache = ResourceDocTag("Cache") + val apiTagLogCache = ResourceDocTag("Log-Cache") val apiTagApiCollection = ResourceDocTag("Api-Collection") diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 8f8968e45..e3f26b02f 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -270,7 +270,7 @@ trait APIMethods510 { EmptyBody, EmptyBody, List($UserNotLoggedIn, UnknownError), - apiTagSystem :: apiTagApi :: Nil, + apiTagSystem :: apiTagApi :: apiTagLogCache :: Nil, Some(List(canGetSystemLogCacheTrace, canGetSystemLogCacheAll))) lazy val logCacheTraceEndpoint: OBPEndpoint = { @@ -301,7 +301,7 @@ trait APIMethods510 { EmptyBody, EmptyBody, List($UserNotLoggedIn, UnknownError), - apiTagSystem :: apiTagApi :: Nil, + apiTagSystem :: apiTagApi :: apiTagLogCache :: Nil, Some(List(canGetSystemLogCacheDebug, canGetSystemLogCacheAll))) lazy val logCacheDebugEndpoint: OBPEndpoint = { @@ -332,7 +332,7 @@ trait APIMethods510 { EmptyBody, EmptyBody, List($UserNotLoggedIn, UnknownError), - apiTagSystem :: apiTagApi :: Nil, + apiTagSystem :: apiTagApi :: apiTagLogCache :: Nil, Some(List(canGetSystemLogCacheInfo, canGetSystemLogCacheAll))) lazy val logCacheInfoEndpoint: OBPEndpoint = { @@ -363,7 +363,7 @@ trait APIMethods510 { EmptyBody, EmptyBody, List($UserNotLoggedIn, UnknownError), - apiTagSystem :: apiTagApi :: Nil, + apiTagSystem :: apiTagApi :: apiTagLogCache :: Nil, Some(List(canGetSystemLogCacheWarning, canGetSystemLogCacheAll))) lazy val logCacheWarningEndpoint: OBPEndpoint = { @@ -394,7 +394,7 @@ trait APIMethods510 { EmptyBody, EmptyBody, List($UserNotLoggedIn, UnknownError), - apiTagSystem :: apiTagApi :: Nil, + apiTagSystem :: apiTagApi :: apiTagLogCache :: Nil, Some(List(canGetSystemLogCacheError, canGetSystemLogCacheAll))) lazy val logCacheErrorEndpoint: OBPEndpoint = { @@ -425,7 +425,7 @@ trait APIMethods510 { EmptyBody, EmptyBody, List($UserNotLoggedIn, UnknownError), - apiTagSystem :: apiTagApi :: Nil, + apiTagSystem :: apiTagApi :: apiTagLogCache :: Nil, Some(List(canGetSystemLogCacheAll))) lazy val logCacheAllEndpoint: OBPEndpoint = { From d4605b27d742211a2d32a2c19fea1ec40f097c00 Mon Sep 17 00:00:00 2001 From: karmaking Date: Wed, 7 Jan 2026 19:16:01 +0100 Subject: [PATCH 18/48] merge test error reporting to build action --- .../build_container_develop_branch.yml | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_container_develop_branch.yml b/.github/workflows/build_container_develop_branch.yml index 793a4d81e..a5e8a87dc 100644 --- a/.github/workflows/build_container_develop_branch.yml +++ b/.github/workflows/build_container_develop_branch.yml @@ -1,19 +1,15 @@ -name: Build and publish container develop +name: Build and publish container non develop -# read-write repo token -# access to secrets on: - workflow_dispatch: push: branches: - - develop + - '*' + - '!develop' env: - ## Sets environment variable DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} DOCKER_HUB_REPOSITORY: obp-api - jobs: build: runs-on: ubuntu-latest @@ -33,6 +29,9 @@ jobs: --health-retries 5 steps: - uses: actions/checkout@v4 + - name: Extract branch name + shell: bash + run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" - name: Set up JDK 11 uses: actions/setup-java@v4 with: @@ -41,6 +40,7 @@ jobs: cache: maven - name: Build with Maven run: | + set -o pipefail cp obp-api/src/main/resources/props/sample.props.template obp-api/src/main/resources/props/production.default.props echo connector=star > obp-api/src/main/resources/props/test.default.props echo starConnector_supported_types=mapped,internal >> obp-api/src/main/resources/props/test.default.props @@ -76,7 +76,44 @@ jobs: echo ResetPasswordUrlEnabled=true >> obp-api/src/main/resources/props/test.default.props echo consents.allowed=true >> obp-api/src/main/resources/props/test.default.props - MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod + MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod 2>&1 | tee maven-build.log + + - name: Report failing tests (if any) + if: always() + run: | + echo "Checking build log for failing tests via grep..." + if [ ! -f maven-build.log ]; then + echo "No maven-build.log found; skipping failure scan." + exit 0 + fi + if grep -n "\*\*\* FAILED \*\*\*" maven-build.log; then + echo "Failing tests detected above." + exit 1 + else + echo "No failing tests detected in maven-build.log." + fi + + - name: Upload Maven build log + if: always() + uses: actions/upload-artifact@v4 + with: + name: maven-build-log + if-no-files-found: ignore + path: | + maven-build.log + + - name: Upload test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-reports + if-no-files-found: ignore + path: | + obp-api/target/surefire-reports/** + obp-commons/target/surefire-reports/** + **/target/scalatest-reports/** + **/target/site/surefire-report.html + **/target/site/surefire-report/* - name: Save .war artifact run: | @@ -86,3 +123,5 @@ jobs: with: name: ${{ github.sha }} path: push/ + + From 346cefcc9021c14b433c7c94afcb521266d40523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Tue, 13 Jan 2026 12:08:13 +0100 Subject: [PATCH 19/48] Revert "feature/Remove Sign Up flow from legacy portal" This reverts commit 233af77b753ededc3668f395a62c2446c589bb76. --- .../resources/props/sample.props.template | 26 +-- .../main/scala/code/api/util/Glossary.scala | 6 +- .../code/model/dataAccess/AuthUser.scala | 193 +++++++++++++++++- .../src/main/scala/code/snippet/Login.scala | 7 +- .../code/snippet/OAuthAuthorisation.scala | 9 +- .../src/main/scala/code/snippet/WebUI.scala | 17 +- obp-api/src/main/webapp/index-en.html | 2 +- obp-api/src/main/webapp/index.html | 2 +- obp-api/src/main/webapp/oauth/authorize.html | 2 +- .../main/webapp/templates-hidden/_login.html | 2 +- .../webapp/templates-hidden/default-en.html | 6 +- .../templates-hidden/default-footer.html | 6 +- .../templates-hidden/default-header.html | 6 +- .../main/webapp/templates-hidden/default.html | 6 +- .../test/scala/code/util/OAuthClient.scala | 2 +- 15 files changed, 219 insertions(+), 73 deletions(-) diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 80e0c7725..c0f151d83 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -569,16 +569,15 @@ webui_oauth_1_documentation_url = # Link to OAuth 2.0 glossary on api explorer webui_oauth_2_documentation_url = -# Sign up functionality removed - users are directed to OBP Portal for registration -# The following signup-related properties are no longer used: -# - webui_signup_form_submit_button_value (signup form submit button text) -# - webui_signup_form_title_text (signup form title) -# - webui_signup_body_password_repeat_text (password repeat field text) -# - allow_pre_filled_password (pre-filled password functionality) -# - webui_agree_terms_html (terms agreement checkbox HTML) -# - webui_agree_privacy_policy_url (privacy policy URL for signup) -# - webui_agree_privacy_policy_html_text (privacy policy agreement text) -# - webui_legal_notice_html_text (legal notice for signup forms) +# Link to Privacy Policy on signup page +#webui_signup_form_submit_button_value= +#webui_signup_form_title_text=Sign Up +#webui_signup_body_password_repeat_text=Repeat +#allow_pre_filled_password=true +#webui_agree_terms_html=
    +webui_agree_privacy_policy_url = https://openbankproject.com/privacy-policy +webui_agree_privacy_policy_html_text =
    +#webui_legal_notice_html_text= ## For partner logos and links webui_main_partners=[\ @@ -597,8 +596,8 @@ webui_main_style_sheet = /media/css/website.css # Override certain elements (with important styles) webui_override_style_sheet = -## Link to agree to Terms & Conditions (no longer used - signup removed) -# webui_agree_terms_url = +## Link to agree to Terms & Conditions, shown on signup page +webui_agree_terms_url = ## The Support Email, shown in the bottom page #webui_support_email=contact@openbankproject.com @@ -626,9 +625,6 @@ webui_override_style_sheet = #webui_post_consumer_registration_submit_button_value=Register consumer # OBP Portal URL - base URL for the OBP Portal service -# Used for: -# - User registration: {webui_obp_portal_url}/register (all "Register" links redirect here) -# - Consumer registration: {webui_obp_portal_url}/consumer-registration (default) webui_obp_portal_url = http://localhost:5174 # External Consumer Registration URL - used to redirect "Get API Key" links to an external service diff --git a/obp-api/src/main/scala/code/api/util/Glossary.scala b/obp-api/src/main/scala/code/api/util/Glossary.scala index 15adc55bb..cde7dd1dd 100644 --- a/obp-api/src/main/scala/code/api/util/Glossary.scala +++ b/obp-api/src/main/scala/code/api/util/Glossary.scala @@ -1249,7 +1249,7 @@ object Glossary extends MdcLoggable { | |### 1) Get your App key | - |[Sign up](${APIUtil.getPropsValue("webui_obp_portal_url", "http://localhost:5174")}/register) or [login]($getServerUrl/user_mgt/login) as a developer. + |[Sign up]($getServerUrl/user_mgt/sign_up) or [login]($getServerUrl/user_mgt/login) as a developer. | |Register your App key [HERE](${getConsumerRegistrationUrl()}) | @@ -2305,7 +2305,7 @@ object Glossary extends MdcLoggable { | |### Step 1: Get your App key | - |[Sign up](${APIUtil.getPropsValue("webui_obp_portal_url", "http://localhost:5174")}/register) or [login]($getServerUrl/user_mgt/login) as a developer + |[Sign up]($getServerUrl/user_mgt/sign_up) or [login]($getServerUrl/user_mgt/login) as a developer | |Register your App key [HERE](${getConsumerRegistrationUrl()}) | @@ -2954,7 +2954,7 @@ object Glossary extends MdcLoggable { | |## In order to get an App / Consumer key | -|[Sign up](${APIUtil.getPropsValue("webui_obp_portal_url", "http://localhost:5174")}/register) or [login]($getServerUrl/user_mgt/login) as a developer. +|[Sign up]($getServerUrl/user_mgt/sign_up) or [login]($getServerUrl/user_mgt/login) as a developer. | |Register your App / Consumer [HERE](${getConsumerRegistrationUrl()}) | diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 11efcde0d..de1989065 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -229,7 +229,7 @@ class AuthUser extends MegaProtoUser[AuthUser] with CreatedUpdated with MdcLogga override lazy val password = new MyPasswordNew - // Removed signup password repeat text - not needed with OBP Portal redirect + lazy val signupPasswordRepeatText = getWebUiPropsValue("webui_signup_body_password_repeat_text", S.?("repeat")) class MyPasswordNew extends MappedPassword(this) { lazy val preFilledPassword = if (APIUtil.getPropsAsBoolValue("allow_pre_filled_password", true)) {get.toString} else "" @@ -238,9 +238,14 @@ class AuthUser extends MegaProtoUser[AuthUser] with CreatedUpdated with MdcLogga Full( {appendFieldId( ) } -
    +
    +
    {signupPasswordRepeatText}
    + +
    + +
    ) } } @@ -424,6 +429,7 @@ import net.liftweb.util.Helpers._ override def screenWrap = Full() // define the order fields will appear in forms and output override def fieldOrder = List(id, firstName, lastName, email, username, password, provider) + override def signupFields = List(firstName, lastName, email, username, password) // To force validation of email addresses set this to false (default as of 29 June 2021) override def skipEmailValidation = APIUtil.getPropsAsBoolValue("authUser.skipEmailValidation", false) @@ -692,7 +698,28 @@ import net.liftweb.util.Helpers._ case _ => S.error(S.?("invalid.validation.link")); S.redirectTo(homePage) } - + override def actionsAfterSignup(theUser: TheUserType, func: () => Nothing): Nothing = { + theUser.setValidated(skipEmailValidation).resetUniqueId() + theUser.save + val privacyPolicyValue: String = getWebUiPropsValue("webui_privacy_policy", "") + val termsAndConditionsValue: String = getWebUiPropsValue("webui_terms_and_conditions", "") + // User Agreement table + UserAgreementProvider.userAgreementProvider.vend.createUserAgreement( + theUser.user.foreign.map(_.userId).getOrElse(""), "privacy_conditions", privacyPolicyValue) + UserAgreementProvider.userAgreementProvider.vend.createUserAgreement( + theUser.user.foreign.map(_.userId).getOrElse(""), "terms_and_conditions", termsAndConditionsValue) + if (!skipEmailValidation) { + sendValidationEmail(theUser) + S.notice(S.?("sign.up.message")) + func() + } else { + grantDefaultEntitlementsToAuthUser(theUser) + logUserIn(theUser, () => { + S.notice(S.?("welcome")) + func() + }) + } + } /** * Set this to redirect to a certain page after a failed login */ @@ -701,9 +728,87 @@ import net.liftweb.util.Helpers._ } - // Removed signup-related methods: agreeTermsDiv, legalNoticeDiv, agreePrivacyPolicy - // These were only used in signup forms which now redirect to OBP Portal - // Signup functionality removed - users are directed to OBP Portal for registration + def agreeTermsDiv = { + val webUi = new WebUI + val webUiPropsValue = getWebUiPropsValue("webui_terms_and_conditions", "") + val termsAndConditionsCheckboxTitle = Helper.i18n("terms_and_conditions_checkbox_text", Some("I agree to the above Terms and Conditions")) + val termsAndConditionsCheckboxLabel = Helper.i18n("terms_and_conditions_checkbox_label", Some("Terms and Conditions")) + val agreeTermsHtml = s"""
    + |
    + |
    + | $termsAndConditionsCheckboxLabel + |
    ${webUi.makeHtml(webUiPropsValue)}
    + |
    + | + | + |
    + | """.stripMargin + + scala.xml.Unparsed(agreeTermsHtml) + } + + def legalNoticeDiv = { + val agreeTermsHtml = getWebUiPropsValue("webui_legal_notice_html_text", "") + if(agreeTermsHtml.isEmpty){ + s"" + } else{ + scala.xml.Unparsed(s"""$agreeTermsHtml""") + } + } + + def agreePrivacyPolicy = { + val webUi = new WebUI + val privacyPolicyCheckboxText = Helper.i18n("privacy_policy_checkbox_text", Some("I agree to the above Privacy Policy")) + val privacyPolicyCheckboxLabel = Helper.i18n("privacy_policy_checkbox_label", Some("Privacy Policy")) + val webUiPropsValue = getWebUiPropsValue("webui_privacy_policy", "") + val agreePrivacyPolicy = s"""
    + |
    + |
    + | $privacyPolicyCheckboxLabel + |
    ${webUi.makeHtml(webUiPropsValue)}
    + |
    + | + | + |
    + |
    """.stripMargin + + scala.xml.Unparsed(agreePrivacyPolicy) + } + def enableDisableSignUpButton = { + val javaScriptCode = """""".stripMargin + + scala.xml.Unparsed(javaScriptCode) + } + + def signupFormTitle = getWebUiPropsValue("webui_signup_form_title_text", S.?("sign.up")) + + override def signupXhtml (user:AuthUser) = { +
    +
    +

    {signupFormTitle}

    + {legalNoticeDiv} +
    + {localForm(user, false, signupFields)} + {agreeTermsDiv} + {agreePrivacyPolicy} +
    + +
    + {enableDisableSignUpButton} +
    +
    + } override def localForm(user: TheUserType, ignorePassword: Boolean, fields: List[FieldPointerType]): NodeSeq = { @@ -713,11 +818,18 @@ import net.liftweb.util.Helpers._ if field.show_? && (!ignorePassword || !pointer.isPasswordField_?) form <- field.toForm.toList } yield { -
    - - {form} -
    -
    + if(field.uniqueFieldId.getOrElse("") == "authuser_password") { +
    + + {form} +
    + } else { +
    + + {form} +
    +
    + } } } @@ -1498,8 +1610,67 @@ def restoreSomeSessions(): Unit = { val usernames: List[String] = this.getResourceUsersByEmail(email).map(_.user.name) findAll(ByList(this.username, usernames)) } + def signupSubmitButtonValue() = getWebUiPropsValue("webui_signup_form_submit_button_value", S.?("sign.up")) + //overridden to allow redirect to loginRedirect after signup. This is mostly to allow + // loginFirst menu items to work if the user doesn't have an account. Without this, + // if a user tries to access a logged-in only page, and then signs up, they don't get redirected + // back to the proper page. + override def signup = { + val theUser: TheUserType = mutateUserOnSignup(createNewUserInstance()) + val theName = signUpPath.mkString("") + //Check the internal redirect, in case for open redirect issue. + // variable redir is from loginRedirect, it is set-up in OAuthAuthorisation.scala as following code: + // val currentUrl = ObpS.uriAndQueryString.getOrElse("/") + // AuthUser.loginRedirect.set(Full(Helpers.appendParams(currentUrl, List((LogUserOutParam, "false"))))) + val loginRedirectSave = loginRedirect.is + + def testSignup() { + validateSignup(theUser) match { + case Nil => + //here we check loginRedirectSave (different from implementation in super class) + val redir = loginRedirectSave match { + case Full(url) => + loginRedirect(Empty) + url + case _ => + //if the register page url (user_mgt/sign_up?after-signup=link-to-customer) contains the parameter + //after-signup=link-to-customer,then it will redirect to the on boarding customer page. + ObpS.param("after-signup") match { + case url if (url.equals("link-to-customer")) => + "/add-user-auth-context-update-request" + case _ => + homePage + } + } + if (Helper.isValidInternalRedirectUrl(redir.toString)) { + actionsAfterSignup(theUser, () => { + S.redirectTo(redir) + }) + } else { + S.error(S.?(ErrorMessages.InvalidInternalRedirectUrl)) + logger.info(ErrorMessages.InvalidInternalRedirectUrl + loginRedirect.get) + } + + case xs => + xs.foreach{ + e => S.error(e.field.uniqueFieldId.openOrThrowException("There is no uniqueFieldId."), e.msg) + } + signupFunc(Full(innerSignup _)) + } + } + + def innerSignup = { + val bind = "type=submit" #> signupSubmitButton(signupSubmitButtonValue(), testSignup _) + bind(signupXhtml(theUser)) + } + + if(APIUtil.getPropsAsBoolValue("user_invitation.mandatory", false)) + S.redirectTo("/user-invitation-info") + else + innerSignup + } def scrambleAuthUser(userPrimaryKey: UserPrimaryKey): Box[Boolean] = tryo { AuthUser.find(By(AuthUser.user, userPrimaryKey.value)) match { diff --git a/obp-api/src/main/scala/code/snippet/Login.scala b/obp-api/src/main/scala/code/snippet/Login.scala index 1ae8ce83b..a7c6a36c3 100644 --- a/obp-api/src/main/scala/code/snippet/Login.scala +++ b/obp-api/src/main/scala/code/snippet/Login.scala @@ -70,11 +70,8 @@ class Login { href getOrElse "#" } & { ".signup [href]" #> { - val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") - s"$portalUrl/register" - } & - ".signup [target]" #> "_blank" & - ".signup [rel]" #> "noopener" + AuthUser.signUpPath.foldLeft("")(_ + "/" + _) + } } } } diff --git a/obp-api/src/main/scala/code/snippet/OAuthAuthorisation.scala b/obp-api/src/main/scala/code/snippet/OAuthAuthorisation.scala index be038b035..66a598627 100644 --- a/obp-api/src/main/scala/code/snippet/OAuthAuthorisation.scala +++ b/obp-api/src/main/scala/code/snippet/OAuthAuthorisation.scala @@ -46,7 +46,6 @@ import net.liftweb.http.S import net.liftweb.util.Helpers._ import net.liftweb.util.{CssSel, Helpers, Props} import code.api.oauth1a.OauthParams._ -import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import scala.xml.NodeSeq @@ -151,12 +150,8 @@ object OAuthAuthorisation { href getOrElse "#" } & - ".signup [href]" #> { - val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") - s"$portalUrl/register" - } & - ".signup [target]" #> "_blank" & - ".signup [rel]" #> "noopener" + ".signup [href]" #> + AuthUser.signUpPath.foldLeft("")(_ + "/" + _) } } case _ => error("Application not found") diff --git a/obp-api/src/main/scala/code/snippet/WebUI.scala b/obp-api/src/main/scala/code/snippet/WebUI.scala index c8861688b..5b0704a02 100644 --- a/obp-api/src/main/scala/code/snippet/WebUI.scala +++ b/obp-api/src/main/scala/code/snippet/WebUI.scala @@ -550,21 +550,8 @@ class WebUI extends MdcLoggable{ def userIsLoggedIn: CssSel = { if(AuthUser.loggedIn_?) "#register-link [href]" #> scala.xml.Unparsed(s"/already-logged-in") - else { - val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") - val registerUrl = s"$portalUrl/register" - "#register-link [href]" #> scala.xml.Unparsed(registerUrl) & - "#register-link [target]" #> "_blank" & - "#register-link [rel]" #> "noopener" - } - } - - def portalRegisterLink: CssSel = { - val portalUrl = getWebUiPropsValue("webui_obp_portal_url", "http://localhost:5174") - val registerUrl = s"$portalUrl/register" - "a [href]" #> scala.xml.Unparsed(registerUrl) & - "a [target]" #> "_blank" & - "a [rel]" #> "noopener" + else + "#register-link [href]" #> scala.xml.Unparsed(s"/user_mgt/sign_up") } def alreadyLoggedIn: CssSel = { diff --git a/obp-api/src/main/webapp/index-en.html b/obp-api/src/main/webapp/index-en.html index 32075b8b4..a0dd0210c 100644 --- a/obp-api/src/main/webapp/index-en.html +++ b/obp-api/src/main/webapp/index-en.html @@ -59,7 +59,7 @@ Berlin 13359, Germany

    -

    +

    .

    diff --git a/obp-api/src/main/webapp/index.html b/obp-api/src/main/webapp/index.html index 92fabd6ba..54b4d75a3 100644 --- a/obp-api/src/main/webapp/index.html +++ b/obp-api/src/main/webapp/index.html @@ -59,7 +59,7 @@ Berlin 13359, Germany

    Create an account

    -

    First, create a free developer account on this sandbox and request a developer key. You will be asked to submit basic information about your app at this stage. Register for an account +

    First, create a free developer account on this sandbox and request a developer key. You will be asked to submit basic information about your app at this stage. Register for an account .

    diff --git a/obp-api/src/main/webapp/oauth/authorize.html b/obp-api/src/main/webapp/oauth/authorize.html index a71babac7..b4d7678a0 100644 --- a/obp-api/src/main/webapp/oauth/authorize.html +++ b/obp-api/src/main/webapp/oauth/authorize.html @@ -40,7 +40,7 @@
    Don't have an account? - Register + Register
    diff --git a/obp-api/src/main/webapp/templates-hidden/_login.html b/obp-api/src/main/webapp/templates-hidden/_login.html index 0b91a507c..c96de62e2 100644 --- a/obp-api/src/main/webapp/templates-hidden/_login.html +++ b/obp-api/src/main/webapp/templates-hidden/_login.html @@ -42,7 +42,7 @@
    Don't have an account? - Register + Register
    diff --git a/obp-api/src/main/webapp/templates-hidden/default-en.html b/obp-api/src/main/webapp/templates-hidden/default-en.html index 9da6dba6d..2b2e4f831 100644 --- a/obp-api/src/main/webapp/templates-hidden/default-en.html +++ b/obp-api/src/main/webapp/templates-hidden/default-en.html @@ -143,7 +143,7 @@ Berlin 13359, Germany
  • @@ -198,7 +198,7 @@ Berlin 13359, Germany
  • @@ -235,7 +235,7 @@ Berlin 13359, Germany Sofit
  • - + On Board
  • diff --git a/obp-api/src/main/webapp/templates-hidden/default-footer.html b/obp-api/src/main/webapp/templates-hidden/default-footer.html index 819ba810c..74a60838b 100644 --- a/obp-api/src/main/webapp/templates-hidden/default-footer.html +++ b/obp-api/src/main/webapp/templates-hidden/default-footer.html @@ -148,7 +148,7 @@ Berlin 13359, Germany
  • @@ -208,7 +208,7 @@ Berlin 13359, Germany
  • @@ -248,7 +248,7 @@ Berlin 13359, Germany Sofit
  • - + On Board
  • diff --git a/obp-api/src/main/webapp/templates-hidden/default-header.html b/obp-api/src/main/webapp/templates-hidden/default-header.html index c5079d3d9..fba6bbb16 100644 --- a/obp-api/src/main/webapp/templates-hidden/default-header.html +++ b/obp-api/src/main/webapp/templates-hidden/default-header.html @@ -143,7 +143,7 @@ Berlin 13359, Germany
  • @@ -198,7 +198,7 @@ Berlin 13359, Germany
  • @@ -236,7 +236,7 @@ Berlin 13359, Germany Sofit
  • - + On Board
  • diff --git a/obp-api/src/main/webapp/templates-hidden/default.html b/obp-api/src/main/webapp/templates-hidden/default.html index c2ec26e45..4eb5915ca 100644 --- a/obp-api/src/main/webapp/templates-hidden/default.html +++ b/obp-api/src/main/webapp/templates-hidden/default.html @@ -143,7 +143,7 @@ Berlin 13359, Germany
  • @@ -198,7 +198,7 @@ Berlin 13359, Germany
  • @@ -235,7 +235,7 @@ Berlin 13359, Germany Sofit
  • - + On Board
  • diff --git a/obp-api/src/test/scala/code/util/OAuthClient.scala b/obp-api/src/test/scala/code/util/OAuthClient.scala index 4f81b1ad4..d930f85ee 100644 --- a/obp-api/src/test/scala/code/util/OAuthClient.scala +++ b/obp-api/src/test/scala/code/util/OAuthClient.scala @@ -67,7 +67,7 @@ trait DefaultProvider extends Provider { val requestTokenUrl = baseUrl + "/oauth/initiate" val accessTokenUrl = baseUrl + "/oauth/token" val authorizeUrl = baseUrl + "/oauth/authorize" - val signupUrl = Some(APIUtil.getPropsValue("webui_obp_portal_url", "http://localhost:5174") + "/register") + val signupUrl = Some(baseUrl + "/user_mgt/sign_up") lazy val oAuthProvider : OAuthProvider = new DefaultOAuthProvider(requestTokenUrl, accessTokenUrl, authorizeUrl) From d32947ba062c803682a34a53b72ecb52f91e3ab5 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 17 Dec 2025 18:27:42 +0100 Subject: [PATCH 20/48] refactor/Introduce http4s routes for v7.0.0 and update API resource docs - Add `Http4sEndpoint` type alias and `http4sPartialFunction` in APIUtil for handling http4s routes - Refactor Http4s700 to define routes as standalone functions (e.g., `root`, `getBanks`) within Implementations7_0_0 object - Attach resource documentation to each route for better maintainability - Create a unified `allRoutes` combining v7.0.0 route handlers - Update imports and clean up unused references --- .../main/scala/code/api/util/APIUtil.scala | 6 +- .../scala/code/api/v7_0_0/Http4s700.scala | 130 +++++++++++++----- 2 files changed, 101 insertions(+), 35 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index d6fb5dbb4..381b0c283 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -27,6 +27,7 @@ TESOBE (http://www.tesobe.com/) package code.api.util import bootstrap.liftweb.CustomDBVendor +import cats.effect.IO import code.accountholders.AccountHolders import code.api.Constant._ import code.api.OAuthHandshake._ @@ -96,6 +97,7 @@ import net.liftweb.util.Helpers._ import net.liftweb.util._ import org.apache.commons.io.IOUtils import org.apache.commons.lang3.StringUtils +import org.http4s.HttpRoutes import java.io.InputStream import java.net.URLDecoder @@ -1636,7 +1638,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ isFeatured: Boolean = false, specialInstructions: Option[String] = None, var specifiedUrl: Option[String] = None, // A derived value: Contains the called version (added at run time). See the resource doc for resource doc! - createdByBankId: Option[String] = None //we need to filter the resource Doc by BankId + createdByBankId: Option[String] = None, //we need to filter the resource Doc by BankId + http4sPartialFunction: Http4sEndpoint = None // http4s endpoint handler ) { // this code block will be merged to constructor. { @@ -2789,6 +2792,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ type OBPEndpoint = PartialFunction[Req, CallContext => Box[JsonResponse]] type OBPReturnType[T] = Future[(T, Option[CallContext])] + type Http4sEndpoint = Option[HttpRoutes[IO]] def getAllowedEndpoints (endpoints : Iterable[OBPEndpoint], resourceDocs: ArrayBuffer[ResourceDoc]) : List[OBPEndpoint] = { diff --git a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala index 877b91b72..05d4fb414 100644 --- a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala +++ b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala @@ -2,18 +2,23 @@ package code.api.v7_0_0 import cats.data.{Kleisli, OptionT} import cats.effect._ -import cats.implicits._ -import code.api.util.{APIUtil, CustomJsonFormats} +import code.api.Constant._ +import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ +import code.api.util.APIUtil.{EmptyBody, _} +import code.api.util.ApiTag._ +import code.api.util.ErrorMessages._ +import code.api.util.{CustomJsonFormats, NewStyle} import code.api.v4_0_0.JSONFactory400 -import code.bankconnectors.Connector -import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} -import net.liftweb.json.Formats +import com.github.dwickern.macros.NameOf.nameOf +import com.openbankproject.commons.ExecutionContext.Implicits.global +import com.openbankproject.commons.util.{ApiVersion, ApiVersionStatus, ScannedApiVersion} +import net.liftweb.json.{Extraction, Formats} import net.liftweb.json.JsonAST.prettyRender -import net.liftweb.json.Extraction import org.http4s._ import org.http4s.dsl.io._ import org.typelevel.vault.Key +import scala.collection.mutable.ArrayBuffer import scala.concurrent.Future import scala.language.{higherKinds, implicitConversions} @@ -24,12 +29,13 @@ object Http4s700 { implicit val formats: Formats = CustomJsonFormats.formats implicit def convertAnyToJsonString(any: Any): String = prettyRender(Extraction.decompose(any)) - val apiVersion: ScannedApiVersion = ApiVersion.v7_0_0 - val apiVersionString: String = apiVersion.toString + val implementedInApiVersion: ScannedApiVersion = ApiVersion.v7_0_0 + val versionStatus = ApiVersionStatus.STABLE.toString + val resourceDocs = ArrayBuffer[ResourceDoc]() case class CallContext(userId: String, requestId: String) - import cats.effect.unsafe.implicits.global - val callContextKey: Key[CallContext] = Key.newKey[IO, CallContext].unsafeRunSync() + val callContextKey: Key[CallContext] = + Key.newKey[IO, CallContext].unsafeRunSync()(cats.effect.unsafe.IORuntime.global) object CallContextMiddleware { @@ -42,31 +48,87 @@ object Http4s700 { } } - val v700Services: HttpRoutes[IO] = HttpRoutes.of[IO] { - case req @ GET -> Root / "obp" / `apiVersionString` / "root" => - import com.openbankproject.commons.ExecutionContext.Implicits.global - val callContext = req.attributes.lookup(callContextKey).get.asInstanceOf[CallContext] - Ok(IO.fromFuture(IO( - for { - _ <- Future() // Just start async call - } yield { - convertAnyToJsonString( - JSONFactory700.getApiInfoJSON(apiVersion, s"Hello, ${callContext.userId}! Your request ID is ${callContext.requestId}.") - ) - } - ))) + object Implementations7_0_0 { - case req @ GET -> Root / "obp" / `apiVersionString` / "banks" => - import com.openbankproject.commons.ExecutionContext.Implicits.global - Ok(IO.fromFuture(IO( - for { - (banks, callContext) <- code.api.util.NewStyle.function.getBanks(None) - } yield { - convertAnyToJsonString(JSONFactory400.createBanksJson(banks)) - } - ))) + // Common prefix: /obp/v7.0.0 + val prefixPath = Root / ApiPathZero.toString / implementedInApiVersion.toString + + resourceDocs += ResourceDoc( + null, + implementedInApiVersion, + nameOf(root), + "GET", + "/root", + "Get API Info (root)", + s"""Returns information about: + | + |* API version + |* Hosted by information + |* Git Commit + |${userAuthenticationMessage(false)}""", + EmptyBody, + apiInfoJSON, + List(UnknownError, "no connector set"), + apiTagApi :: Nil, + http4sPartialFunction = Some(root) + ) + + // Route: GET /obp/v7.0.0/root + val root: HttpRoutes[IO] = HttpRoutes.of[IO] { + case req @ GET -> `prefixPath` / "root" => + val callContext = req.attributes.lookup(callContextKey).get.asInstanceOf[CallContext] + Ok(IO.fromFuture(IO( + for { + _ <- Future() // Just start async call + } yield { + convertAnyToJsonString( + JSONFactory700.getApiInfoJSON(implementedInApiVersion, s"Hello, ${callContext.userId}! Your request ID is ${callContext.requestId}.") + ) + } + ))) + } + + resourceDocs += ResourceDoc( + null, + implementedInApiVersion, + nameOf(getBanks), + "GET", + "/banks", + "Get Banks", + s"""Get banks on this API instance + |Returns a list of banks supported on this server: + | + |* ID used as parameter in URLs + |* Short and full name of bank + |* Logo URL + |* Website + |${userAuthenticationMessage(false)}""", + EmptyBody, + banksJSON, + List(UnknownError), + apiTagBank :: Nil, + http4sPartialFunction = Some(getBanks) + ) + + // Route: GET /obp/v7.0.0/banks + val getBanks: HttpRoutes[IO] = HttpRoutes.of[IO] { + case req @ GET -> `prefixPath` / "banks" => + import com.openbankproject.commons.ExecutionContext.Implicits.global + Ok(IO.fromFuture(IO( + for { + (banks, callContext) <- NewStyle.function.getBanks(None) + } yield { + convertAnyToJsonString(JSONFactory400.createBanksJson(banks)) + } + ))) + } + + // All routes combined + val allRoutes: HttpRoutes[IO] = + Kleisli[HttpF, Request[IO], Response[IO]] { req: Request[IO] => + root(req).orElse(getBanks(req)) + } } - val wrappedRoutesV700Services: HttpRoutes[IO] = CallContextMiddleware.withCallContext(v700Services) + val wrappedRoutesV700Services: HttpRoutes[IO] = CallContextMiddleware.withCallContext(Implementations7_0_0.allRoutes) } - From 7c9095f0aade4f47dbaf45f39f0af5954f280e7c Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 17 Dec 2025 19:19:19 +0100 Subject: [PATCH 21/48] feature/Get resource docs endpoint for v7.0.0 - Introduce `getResourceDocsObpV700` to handle resource docs retrieval for API version 7.0.0 - Add `getResourceDocsList` helper function for fetching version-specific resource docs - Update `allRoutes` to include the new endpoint - Modify imports to include necessary utilities and remove unused references --- .../scala/code/api/v7_0_0/Http4s700.scala | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala index 05d4fb414..40fdbb5b2 100644 --- a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala +++ b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala @@ -3,17 +3,19 @@ package code.api.v7_0_0 import cats.data.{Kleisli, OptionT} import cats.effect._ import code.api.Constant._ +import code.api.ResourceDocs1_4_0.ResourceDocsAPIMethodsUtil import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil.{EmptyBody, _} import code.api.util.ApiTag._ import code.api.util.ErrorMessages._ -import code.api.util.{CustomJsonFormats, NewStyle} +import code.api.util.{ApiVersionUtils, CustomJsonFormats, NewStyle, ScannedApis} +import code.api.v1_4_0.JSONFactory1_4_0 import code.api.v4_0_0.JSONFactory400 import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.util.{ApiVersion, ApiVersionStatus, ScannedApiVersion} -import net.liftweb.json.{Extraction, Formats} import net.liftweb.json.JsonAST.prettyRender +import net.liftweb.json.{Extraction, Formats} import org.http4s._ import org.http4s.dsl.io._ import org.typelevel.vault.Key @@ -53,6 +55,14 @@ object Http4s700 { // Common prefix: /obp/v7.0.0 val prefixPath = Root / ApiPathZero.toString / implementedInApiVersion.toString + private def getResourceDocsList(requestedApiVersion: ApiVersion): List[ResourceDoc] = { + requestedApiVersion match { + case version: ScannedApiVersion => + ScannedApis.versionMapScannedApis.get(version).map(_.allResourceDocs.toList).getOrElse(Nil) + case _ => Nil + } + } + resourceDocs += ResourceDoc( null, implementedInApiVersion, @@ -123,10 +133,30 @@ object Http4s700 { ))) } + val getResourceDocsObpV700: HttpRoutes[IO] = HttpRoutes.of[IO] { + case req @ GET -> `prefixPath` / "resource-docs" / requestedApiVersionString / "obp" => + import com.openbankproject.commons.ExecutionContext.Implicits.global + val logic = for { + httpParams <- NewStyle.function.extractHttpParamsFromUrl(req.uri.renderString) + tagsParam = httpParams.filter(_.name == "tags").map(_.values).headOption + functionsParam = httpParams.filter(_.name == "functions").map(_.values).headOption + localeParam = httpParams.filter(param => param.name == "locale" || param.name == "language").map(_.values).flatten.headOption + contentParam = httpParams.filter(_.name == "content").map(_.values).flatten.flatMap(ResourceDocsAPIMethodsUtil.stringToContentParam).headOption + apiCollectionIdParam = httpParams.filter(_.name == "api-collection-id").map(_.values).flatten.headOption + tags = tagsParam.map(_.map(ResourceDocTag(_))) + functions = functionsParam.map(_.toList) + requestedApiVersion <- Future(ApiVersionUtils.valueOf(requestedApiVersionString)) + resourceDocs = getResourceDocsList(requestedApiVersion) + filteredDocs = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, tags, functions) + resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(filteredDocs, isVersion4OrHigher = true, localeParam) + } yield convertAnyToJsonString(resourceDocsJson) + Ok(IO.fromFuture(IO(logic))) + } + // All routes combined val allRoutes: HttpRoutes[IO] = Kleisli[HttpF, Request[IO], Response[IO]] { req: Request[IO] => - root(req).orElse(getBanks(req)) + root(req).orElse(getBanks(req)).orElse(getResourceDocsObpV700(req)) } } From ad7b6fe357edfbf36a47e489b393d97a2edf3969 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 17 Dec 2025 22:42:12 +0100 Subject: [PATCH 22/48] refactor(Http4sServer): Reorder service initialization and improve comments --- .../main/scala/bootstrap/http4s/Http4sServer.scala | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala b/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala index 8a8b3366f..72b0574d2 100644 --- a/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala +++ b/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala @@ -11,17 +11,16 @@ import org.http4s.implicits._ import scala.language.higherKinds object Http4sServer extends IOApp { - val services: Kleisli[({type λ[β$0$] = OptionT[IO, β$0$]})#λ, Request[IO], Response[IO]] = - code.api.v7_0_0.Http4s700.wrappedRoutesV700Services - - val httpApp: Kleisli[IO, Request[IO], Response[IO]] = (services).orNotFound - - //Start OBP relevant objects, and settings + //Start OBP relevant objects and settings; this step MUST be executed first new bootstrap.http4s.Http4sBoot().boot val port = APIUtil.getPropsAsIntValue("http4s.port",8181) val host = APIUtil.getPropsValue("http4s.host","127.0.0.1") + val services: Kleisli[({type λ[β$0$] = OptionT[IO, β$0$]})#λ, Request[IO], Response[IO]] = + code.api.v7_0_0.Http4s700.wrappedRoutesV700Services + + val httpApp: Kleisli[IO, Request[IO], Response[IO]] = (services).orNotFound override def run(args: List[String]): IO[ExitCode] = EmberServerBuilder .default[IO] From da29c29c4097f6c19c101e06d062d5fdf6448172 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 17 Dec 2025 23:51:37 +0100 Subject: [PATCH 23/48] feature/Support API version 7.0.0 - Add `v7_0_0` to supported API versions in `ApiVersionUtils` - Update `Http4s700` to return pre-defined resource docs instead of scanning for version 7.0.0 --- obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala | 2 ++ obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala b/obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala index 5e93b6f7b..f7285febb 100644 --- a/obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala +++ b/obp-api/src/main/scala/code/api/util/ApiVersionUtils.scala @@ -19,6 +19,7 @@ object ApiVersionUtils { v5_0_0 :: v5_1_0 :: v6_0_0 :: + v7_0_0 :: `dynamic-endpoint` :: `dynamic-entity` :: scannedApis @@ -41,6 +42,7 @@ object ApiVersionUtils { case v5_0_0.fullyQualifiedVersion | v5_0_0.apiShortVersion => v5_0_0 case v5_1_0.fullyQualifiedVersion | v5_1_0.apiShortVersion => v5_1_0 case v6_0_0.fullyQualifiedVersion | v6_0_0.apiShortVersion => v6_0_0 + case v7_0_0.fullyQualifiedVersion | v7_0_0.apiShortVersion => v7_0_0 case `dynamic-endpoint`.fullyQualifiedVersion | `dynamic-endpoint`.apiShortVersion => `dynamic-endpoint` case `dynamic-entity`.fullyQualifiedVersion | `dynamic-entity`.apiShortVersion => `dynamic-entity` case version if(scannedApis.map(_.fullyQualifiedVersion).contains(version)) diff --git a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala index 40fdbb5b2..d491e7be3 100644 --- a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala +++ b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala @@ -8,7 +8,7 @@ import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil.{EmptyBody, _} import code.api.util.ApiTag._ import code.api.util.ErrorMessages._ -import code.api.util.{ApiVersionUtils, CustomJsonFormats, NewStyle, ScannedApis} +import code.api.util.{ApiVersionUtils, CustomJsonFormats, NewStyle} import code.api.v1_4_0.JSONFactory1_4_0 import code.api.v4_0_0.JSONFactory400 import com.github.dwickern.macros.NameOf.nameOf @@ -58,7 +58,7 @@ object Http4s700 { private def getResourceDocsList(requestedApiVersion: ApiVersion): List[ResourceDoc] = { requestedApiVersion match { case version: ScannedApiVersion => - ScannedApis.versionMapScannedApis.get(version).map(_.allResourceDocs.toList).getOrElse(Nil) + resourceDocs.toList case _ => Nil } } From 4a0eded98cd7a0727f793e8e89d61abbf71ea437 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 18 Dec 2025 09:07:24 +0100 Subject: [PATCH 24/48] refactor/Http4sServer: Update default http4s.port from 8181 to 8086 --- obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala b/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala index 72b0574d2..8207e7268 100644 --- a/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala +++ b/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala @@ -14,7 +14,7 @@ object Http4sServer extends IOApp { //Start OBP relevant objects and settings; this step MUST be executed first new bootstrap.http4s.Http4sBoot().boot - val port = APIUtil.getPropsAsIntValue("http4s.port",8181) + val port = APIUtil.getPropsAsIntValue("http4s.port",8086) val host = APIUtil.getPropsValue("http4s.host","127.0.0.1") val services: Kleisli[({type λ[β$0$] = OptionT[IO, β$0$]})#λ, Request[IO], Response[IO]] = From f816f230b52b04f14a6a2d9e6dc1969a6531d974 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 18 Dec 2025 09:18:02 +0100 Subject: [PATCH 25/48] feature/Enhance resource docs handling for v7.0.0 - Update `getResourceDocsList` to include v7.0.0 in `ResourceDocsAPIMethods` - Modify `Http4s700` to utilize centralized `ResourceDocs140` for fetching resource docs - Simplify resource docs filtering logic for v7.0.0 with tailored handling --- .../ResourceDocsAPIMethods.scala | 87 ++++++++++--------- .../scala/code/api/v7_0_0/Http4s700.scala | 11 +-- 2 files changed, 47 insertions(+), 51 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala index fc6c5995e..bf95b10b0 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/ResourceDocsAPIMethods.scala @@ -1,8 +1,10 @@ package code.api.ResourceDocs1_4_0 -import code.api.Constant.{GET_DYNAMIC_RESOURCE_DOCS_TTL, GET_STATIC_RESOURCE_DOCS_TTL, PARAM_LOCALE, HostName} +import code.api.Constant.{GET_DYNAMIC_RESOURCE_DOCS_TTL, GET_STATIC_RESOURCE_DOCS_TTL, HostName, PARAM_LOCALE} import code.api.OBPRestHelper import code.api.cache.Caching +import code.api.dynamic.endpoint.OBPAPIDynamicEndpoint +import code.api.dynamic.entity.OBPAPIDynamicEntity import code.api.util.APIUtil._ import code.api.util.ApiRole.{canReadDynamicResourceDocsAtOneBank, canReadResourceDoc} import code.api.util.ApiTag._ @@ -20,12 +22,9 @@ import code.api.v4_0_0.{APIMethods400, OBPAPI4_0_0} import code.api.v5_0_0.OBPAPI5_0_0 import code.api.v5_1_0.OBPAPI5_1_0 import code.api.v6_0_0.OBPAPI6_0_0 -import code.api.dynamic.endpoint.OBPAPIDynamicEndpoint -import code.api.dynamic.entity.OBPAPIDynamicEntity import code.apicollectionendpoint.MappedApiCollectionEndpointsProvider import code.util.Helper import code.util.Helper.{MdcLoggable, ObpS, SILENCE_IS_GOLDEN} -import net.liftweb.http.S import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model.enums.ContentParam import com.openbankproject.commons.model.enums.ContentParam.{ALL, DYNAMIC, STATIC} @@ -33,7 +32,7 @@ import com.openbankproject.commons.model.{BankId, ListResult, User} import com.openbankproject.commons.util.ApiStandards._ import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} import net.liftweb.common.{Box, Empty, Full} -import net.liftweb.http.{InMemoryResponse, LiftRules, PlainTextResponse} +import net.liftweb.http.{InMemoryResponse, LiftRules, PlainTextResponse, S} import net.liftweb.json import net.liftweb.json.JsonAST.{JField, JString, JValue} import net.liftweb.json._ @@ -118,6 +117,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth logger.debug(s"getResourceDocsList says requestedApiVersion is $requestedApiVersion") val resourceDocs = requestedApiVersion match { + case ApiVersion.v7_0_0 => code.api.v7_0_0.Http4s700.resourceDocs case ApiVersion.v6_0_0 => OBPAPI6_0_0.allResourceDocs case ApiVersion.v5_1_0 => OBPAPI5_1_0.allResourceDocs case ApiVersion.v5_0_0 => OBPAPI5_0_0.allResourceDocs @@ -139,6 +139,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth logger.debug(s"There are ${resourceDocs.length} resource docs available to $requestedApiVersion") val versionRoutes = requestedApiVersion match { + case ApiVersion.v7_0_0 => Nil case ApiVersion.v6_0_0 => OBPAPI6_0_0.routes case ApiVersion.v5_1_0 => OBPAPI5_1_0.routes case ApiVersion.v5_0_0 => OBPAPI5_0_0.routes @@ -165,7 +166,10 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth val versionRoutesClasses = versionRoutes.map { vr => vr.getClass } // Only return the resource docs that have available routes - val activeResourceDocs = resourceDocs.filter(rd => versionRoutesClasses.contains(rd.partialFunction.getClass)) + val activeResourceDocs = requestedApiVersion match { + case ApiVersion.v7_0_0 => resourceDocs + case _ => resourceDocs.filter(rd => versionRoutesClasses.contains(rd.partialFunction.getClass)) + } logger.debug(s"There are ${activeResourceDocs.length} resource docs available to $requestedApiVersion") @@ -176,8 +180,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth requestedApiVersion match { // only `obp` standard show the `localResourceDocs` - case version: ScannedApiVersion - if(version.apiStandard == obp.toString) => + case version: ScannedApiVersion + if(version.apiStandard == obp.toString) => activePlusLocalResourceDocs ++= localResourceDocs case _ => ; // all other standards only show their own apis. } @@ -218,7 +222,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth /** - * + * * @param requestedApiVersion * @param resourceDocTags * @param partialFunctionNames @@ -285,9 +289,9 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth val allDocs = staticDocs.map(_ ++ filteredDocs) resourceDocsToResourceDocJson(allDocs, resourceDocTags, partialFunctionNames, isVersion4OrHigher, locale) - + } - + def getResourceDocsObpDynamicCached( resourceDocTags: Option[List[ResourceDocTag]], partialFunctionNames: Option[List[String]], @@ -322,7 +326,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } resourceDocsToResourceDocJson(Some(filteredDocs), resourceDocTags, partialFunctionNames, isVersion4OrHigher, locale) - + } @@ -347,7 +351,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth def getResourceDocsDescription(isBankLevelResourceDoc: Boolean) = { val endpointBankIdPath = if (isBankLevelResourceDoc) "/banks/BANK_ID" else "" - + s"""Get documentation about the RESTful resources on this server including example bodies for POST and PUT requests. | |This is the native data format used to document OBP endpoints. Each endpoint has a Resource Doc (a Scala case class) defined in the source code. @@ -368,8 +372,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth | if set content=dynamic, only show dynamic endpoints, if content=static, only show the static endpoints. if omit this parameter, we will show all the endpoints. | | You may need some other language resource docs, now we support en_GB and es_ES at the moment. - | - | You can filter with api-collection-id, but api-collection-id can not be used with others together. If api-collection-id is used in URL, it will ignore all other parameters. + | + | You can filter with api-collection-id, but api-collection-id can not be used with others together. If api-collection-id is used in URL, it will ignore all other parameters. | |See the Resource Doc endpoint for more information. | @@ -396,8 +400,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth | """ } - - + + localResourceDocs += ResourceDoc( getResourceDocsObp, implementedInApiVersion, @@ -407,7 +411,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth "Get Resource Docs.", getResourceDocsDescription(false), EmptyBody, - EmptyBody, + EmptyBody, UnknownError :: Nil, List(apiTagDocumentation, apiTagApi), Some(List(canReadResourceDoc)) @@ -424,7 +428,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth getApiLevelResourceDocs(cc,requestedApiVersionString, tags, partialFunctions, locale, contentParam, apiCollectionIdParam,false) } } - + localResourceDocs += ResourceDoc( getResourceDocsObpV400, implementedInApiVersion, @@ -439,7 +443,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth List(apiTagDocumentation, apiTagApi), Some(List(canReadResourceDoc)) ) - + lazy val getResourceDocsObpV400 : OBPEndpoint = { case "resource-docs" :: requestedApiVersionString :: "obp" :: Nil JsonGet _ => { val (tags, partialFunctions, locale, contentParam, apiCollectionIdParam) = ResourceDocsAPIMethodsUtil.getParams() @@ -490,7 +494,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth Some(isVersion4OrHigher) ) json <- locale match { - case _ if (apiCollectionIdParam.isDefined) => + case _ if (apiCollectionIdParam.isDefined) => NewStyle.function.tryons(s"$UnknownError Can not prepare OBP resource docs.", 500, callContext) { val operationIds = MappedApiCollectionEndpointsProvider.getApiCollectionEndpoints(apiCollectionIdParam.getOrElse("")).map(_.operationId).map(getObpFormatOperationId) val resourceDocs = ResourceDoc.getResourceDocs(operationIds) @@ -647,7 +651,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth |See the Resource Doc endpoint for more information. | | Note: Resource Docs are cached, TTL is ${GET_DYNAMIC_RESOURCE_DOCS_TTL} seconds - | + | |Following are more examples: |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/swagger |${getObpApiRoot}/v3.1.0/resource-docs/v3.1.0/swagger?tags=Account,Bank @@ -694,7 +698,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth Some(isVersion4OrHigher) ) cacheValueFromRedis = Caching.getStaticSwaggerDocCache(cacheKey) - + swaggerJValue <- if (cacheValueFromRedis.isDefined) { NewStyle.function.tryons(s"$UnknownError Can not convert internal swagger file from cache.", 400, cc.callContext) {json.parse(cacheValueFromRedis.get)} } else { @@ -747,7 +751,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth | • All endpoints are given one or more tags which are used for grouping | • Empty values will return error OBP-10053 | - |**functions** - Filter by function names (comma-separated list) + |**functions** - Filter by function names (comma-separated list) | • Example: ?functions=getBanks,bankById | • Each endpoint is implemented in the OBP Scala code by a 'function' | • Empty values will return error OBP-10054 @@ -815,26 +819,26 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth List(apiTagDocumentation, apiTagApi) ) - // Note: OpenAPI 3.1 YAML endpoint (/resource-docs/API_VERSION/openapi.yaml) - // is implemented using Lift's serve mechanism in ResourceDocs140.scala to properly + // Note: OpenAPI 3.1 YAML endpoint (/resource-docs/API_VERSION/openapi.yaml) + // is implemented using Lift's serve mechanism in ResourceDocs140.scala to properly // handle YAML content type. It provides the same functionality as the JSON endpoint // but returns OpenAPI documentation in YAML format instead of JSON. /** * OpenAPI 3.1 endpoint with comprehensive parameter validation. - * + * * This endpoint generates OpenAPI 3.1 documentation with the following validated query parameters: * - tags: Comma-separated list of tags to filter endpoints (e.g., ?tags=Account,Bank) * - functions: Comma-separated list of function names to filter endpoints - * - content: Filter type - "static", "dynamic", or "all" + * - content: Filter type - "static", "dynamic", or "all" * - locale: Language code for localization (e.g., "en_GB", "es_ES") * - api-collection-id: UUID to filter by specific API collection - * + * * Parameter validation guards ensure: * - Empty parameters (e.g., ?tags=) return 400 error * - Invalid content values return 400 error with valid options * - All parameters are properly trimmed and sanitized - * + * * Examples: * - ?content=static&tags=Account-Firehose * - ?tags=Account,Bank&functions=getBanks,bankById @@ -844,7 +848,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth case "resource-docs" :: requestedApiVersionString :: "openapi" :: Nil JsonGet _ => { cc => { implicit val ec = EndpointContext(Some(cc)) - + // Early validation for empty parameters using underlying S to bypass ObpS filtering if (S.param("tags").exists(_.trim.isEmpty)) { Full(errorJsonResponse(InvalidTagsParameter, 400)) @@ -888,7 +892,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth Some(isVersion4OrHigher) ) cacheValueFromRedis = Caching.getStaticSwaggerDocCache(cacheKey) - + openApiJValue <- if (cacheValueFromRedis.isDefined) { NewStyle.function.tryons(s"$UnknownError Can not convert internal openapi file from cache.", 400, cc.callContext) {json.parse(cacheValueFromRedis.get)} } else { @@ -922,8 +926,8 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth } } - // Note: The OpenAPI 3.1 YAML endpoint (/resource-docs/API_VERSION/openapi.yaml) - // is implemented using Lift's serve mechanism in ResourceDocs140.scala to properly + // Note: The OpenAPI 3.1 YAML endpoint (/resource-docs/API_VERSION/openapi.yaml) + // is implemented using Lift's serve mechanism in ResourceDocs140.scala to properly // handle YAML content type and response format, rather than as a standard OBPEndpoint. @@ -1022,7 +1026,7 @@ trait ResourceDocsAPIMethods extends MdcLoggable with APIMethods220 with APIMeth example_request_body = endpointMappingRequestBodyExample, success_response_body = endpointMappingRequestBodyExample ) - + case doc if ( doc.operation_id == buildOperationId(APIMethods400.Implementations4_0_0.implementedInApiVersion, nameOf(APIMethods400.Implementations4_0_0.getDynamicEndpoint)) || doc.operation_id == buildOperationId(APIMethods400.Implementations4_0_0.implementedInApiVersion, nameOf(APIMethods400.Implementations4_0_0.getBankLevelDynamicEndpoint))) => doc.copy(success_response_body = ExampleValue.dynamicEndpointResponseBodyEmptyExample) @@ -1158,7 +1162,7 @@ object ResourceDocsAPIMethodsUtil extends MdcLoggable{ } logger.debug(s"partialFunctionNames is $partialFunctionNames") - val locale = ObpS.param(PARAM_LOCALE).or(ObpS.param("language")) // we used language before, so keep it there. + val locale = ObpS.param(PARAM_LOCALE).or(ObpS.param("language")) // we used language before, so keep it there. logger.debug(s"locale is $locale") // So we can produce a reduced list of resource docs to prevent manual editing of swagger files. @@ -1173,8 +1177,8 @@ object ResourceDocsAPIMethodsUtil extends MdcLoggable{ if x.trim.nonEmpty } yield x.trim logger.debug(s"apiCollectionIdParam is $apiCollectionIdParam") - - + + (tags, partialFunctionNames, locale, contentParam, apiCollectionIdParam) } @@ -1186,8 +1190,8 @@ We don't assume a default catalog (as API Explorer does) so the caller must specify any required filtering by catalog explicitly. */ def filterResourceDocs( - allResources: List[ResourceDoc], - resourceDocTags: Option[List[ResourceDocTag]], + allResources: List[ResourceDoc], + resourceDocTags: Option[List[ResourceDocTag]], partialFunctionNames: Option[List[String]] ) : List[ResourceDoc] = { @@ -1229,7 +1233,7 @@ so the caller must specify any required filtering by catalog explicitly. // tags param was not mentioned in url or was empty, so return all case None => filteredResources3 } - + val resourcesToUse = filteredResources4.toSet.toList @@ -1251,4 +1255,3 @@ so the caller must specify any required filtering by catalog explicitly. } - diff --git a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala index d491e7be3..1f8388ebd 100644 --- a/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala +++ b/obp-api/src/main/scala/code/api/v7_0_0/Http4s700.scala @@ -3,8 +3,8 @@ package code.api.v7_0_0 import cats.data.{Kleisli, OptionT} import cats.effect._ import code.api.Constant._ -import code.api.ResourceDocs1_4_0.ResourceDocsAPIMethodsUtil import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ +import code.api.ResourceDocs1_4_0.{ResourceDocs140, ResourceDocsAPIMethodsUtil} import code.api.util.APIUtil.{EmptyBody, _} import code.api.util.ApiTag._ import code.api.util.ErrorMessages._ @@ -55,13 +55,6 @@ object Http4s700 { // Common prefix: /obp/v7.0.0 val prefixPath = Root / ApiPathZero.toString / implementedInApiVersion.toString - private def getResourceDocsList(requestedApiVersion: ApiVersion): List[ResourceDoc] = { - requestedApiVersion match { - case version: ScannedApiVersion => - resourceDocs.toList - case _ => Nil - } - } resourceDocs += ResourceDoc( null, @@ -146,7 +139,7 @@ object Http4s700 { tags = tagsParam.map(_.map(ResourceDocTag(_))) functions = functionsParam.map(_.toList) requestedApiVersion <- Future(ApiVersionUtils.valueOf(requestedApiVersionString)) - resourceDocs = getResourceDocsList(requestedApiVersion) + resourceDocs = ResourceDocs140.ImplementationsResourceDocs.getResourceDocsList(requestedApiVersion).getOrElse(Nil) filteredDocs = ResourceDocsAPIMethodsUtil.filterResourceDocs(resourceDocs, tags, functions) resourceDocsJson = JSONFactory1_4_0.createResourceDocsJson(filteredDocs, isVersion4OrHigher = true, localeParam) } yield convertAnyToJsonString(resourceDocsJson) From 46bf0ddcfea674d5f2de07e35f44d98a5fe2f0d2 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 18 Dec 2025 14:32:29 +0100 Subject: [PATCH 26/48] docfix/Update .gitignore to exclude `.trae` files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b52072215..c057cc52c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ *.code-workspace .zed .cursor +.trae .classpath .project .cache From 2ab1f4ff3effd5efac3860f9f074b56918ae8652 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 19 Dec 2025 09:06:24 +0100 Subject: [PATCH 27/48] test/ApiVersionUtilsTest: Update expected version count to 25 --- obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala b/obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala index 1a14ed896..05d1bd510 100644 --- a/obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala +++ b/obp-api/src/test/scala/code/util/ApiVersionUtilsTest.scala @@ -20,6 +20,6 @@ class ApiVersionUtilsTest extends V400ServerSetup { versions.map(version => ApiVersionUtils.valueOf(version.fullyQualifiedVersion)) //NOTE, when we added the new version, better fix this number manually. and also check the versions - versions.length shouldBe(24) + versions.length shouldBe(25) }} } \ No newline at end of file From bb8af5059d17cbb38a3fb5ee18a1e82e655e5b0c Mon Sep 17 00:00:00 2001 From: karmaking Date: Mon, 5 Jan 2026 13:24:15 +0100 Subject: [PATCH 28/48] fix restore build pipeline --- .github/workflows/auto_update_base_image.yml | 35 ++++++ .../build_container_develop_branch.yml | 82 ++++++------- .../build_container_non_develop_branch.yml | 114 ++++++++++++++++++ .github/workflows/run_trivy.yml | 54 +++++++++ 4 files changed, 240 insertions(+), 45 deletions(-) create mode 100644 .github/workflows/auto_update_base_image.yml create mode 100644 .github/workflows/build_container_non_develop_branch.yml create mode 100644 .github/workflows/run_trivy.yml diff --git a/.github/workflows/auto_update_base_image.yml b/.github/workflows/auto_update_base_image.yml new file mode 100644 index 000000000..3048faf15 --- /dev/null +++ b/.github/workflows/auto_update_base_image.yml @@ -0,0 +1,35 @@ +name: Regular base image update check +on: + schedule: + - cron: "0 5 * * *" + workflow_dispatch: + +env: + ## Sets environment variable + DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Docker Image Update Checker + id: baseupdatecheck + uses: lucacome/docker-image-update-checker@v2.0.0 + with: + base-image: jetty:9.4-jdk11-alpine + image: ${{ env.DOCKER_HUB_ORGANIZATION }}/obp-api:latest + + - name: Trigger build_container_develop_branch workflow + uses: actions/github-script@v6 + with: + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'build_container_develop_branch.yml', + ref: 'refs/heads/develop' + }); + if: steps.baseupdatecheck.outputs.needs-updating == 'true' diff --git a/.github/workflows/build_container_develop_branch.yml b/.github/workflows/build_container_develop_branch.yml index a5e8a87dc..d3f355042 100644 --- a/.github/workflows/build_container_develop_branch.yml +++ b/.github/workflows/build_container_develop_branch.yml @@ -1,15 +1,19 @@ -name: Build and publish container non develop +name: Build and publish container develop +# read-write repo token +# access to secrets on: + workflow_dispatch: push: branches: - - '*' - - '!develop' + - develop env: + ## Sets environment variable DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} DOCKER_HUB_REPOSITORY: obp-api + jobs: build: runs-on: ubuntu-latest @@ -29,9 +33,6 @@ jobs: --health-retries 5 steps: - uses: actions/checkout@v4 - - name: Extract branch name - shell: bash - run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" - name: Set up JDK 11 uses: actions/setup-java@v4 with: @@ -40,7 +41,6 @@ jobs: cache: maven - name: Build with Maven run: | - set -o pipefail cp obp-api/src/main/resources/props/sample.props.template obp-api/src/main/resources/props/production.default.props echo connector=star > obp-api/src/main/resources/props/test.default.props echo starConnector_supported_types=mapped,internal >> obp-api/src/main/resources/props/test.default.props @@ -76,44 +76,7 @@ jobs: echo ResetPasswordUrlEnabled=true >> obp-api/src/main/resources/props/test.default.props echo consents.allowed=true >> obp-api/src/main/resources/props/test.default.props - MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod 2>&1 | tee maven-build.log - - - name: Report failing tests (if any) - if: always() - run: | - echo "Checking build log for failing tests via grep..." - if [ ! -f maven-build.log ]; then - echo "No maven-build.log found; skipping failure scan." - exit 0 - fi - if grep -n "\*\*\* FAILED \*\*\*" maven-build.log; then - echo "Failing tests detected above." - exit 1 - else - echo "No failing tests detected in maven-build.log." - fi - - - name: Upload Maven build log - if: always() - uses: actions/upload-artifact@v4 - with: - name: maven-build-log - if-no-files-found: ignore - path: | - maven-build.log - - - name: Upload test reports - if: always() - uses: actions/upload-artifact@v4 - with: - name: test-reports - if-no-files-found: ignore - path: | - obp-api/target/surefire-reports/** - obp-commons/target/surefire-reports/** - **/target/scalatest-reports/** - **/target/site/surefire-report.html - **/target/site/surefire-report/* + MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod - name: Save .war artifact run: | @@ -124,4 +87,33 @@ jobs: name: ${{ github.sha }} path: push/ + - name: Build the Docker image + run: | + echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin docker.io + docker build . --file .github/Dockerfile_PreBuild --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop + docker build . --file .github/Dockerfile_PreBuild_OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC + docker push docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }} --all-tags + echo docker done + + - uses: sigstore/cosign-installer@main + + - name: Write signing key to disk (only needed for `cosign sign --key`) + run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key + + - name: Sign container image + run: | + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop-OC + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest-OC + env: + COSIGN_PASSWORD: "${{secrets.COSIGN_PASSWORD}}" + + diff --git a/.github/workflows/build_container_non_develop_branch.yml b/.github/workflows/build_container_non_develop_branch.yml new file mode 100644 index 000000000..946d81de4 --- /dev/null +++ b/.github/workflows/build_container_non_develop_branch.yml @@ -0,0 +1,114 @@ +name: Build and publish container non develop + +on: + push: + branches: + - '*' + - '!develop' + +env: + DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} + DOCKER_HUB_REPOSITORY: obp-api + +jobs: + build: + runs-on: ubuntu-latest + services: + # Label used to access the service container + redis: + # Docker Hub image + image: redis + ports: + # Opens tcp port 6379 on the host and service container + - 6379:6379 + # Set health checks to wait until redis has started + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - uses: actions/checkout@v4 + - name: Extract branch name + shell: bash + run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'adopt' + cache: maven + - name: Build with Maven + run: | + cp obp-api/src/main/resources/props/sample.props.template obp-api/src/main/resources/props/production.default.props + echo connector=star > obp-api/src/main/resources/props/test.default.props + echo starConnector_supported_types=mapped,internal >> obp-api/src/main/resources/props/test.default.props + echo hostname=http://localhost:8016 >> obp-api/src/main/resources/props/test.default.props + echo tests.port=8016 >> obp-api/src/main/resources/props/test.default.props + echo End of minimum settings >> obp-api/src/main/resources/props/test.default.props + echo payments_enabled=false >> obp-api/src/main/resources/props/test.default.props + echo importer_secret=change_me >> obp-api/src/main/resources/props/test.default.props + echo messageQueue.updateBankAccountsTransaction=false >> obp-api/src/main/resources/props/test.default.props + echo messageQueue.createBankAccounts=false >> obp-api/src/main/resources/props/test.default.props + echo allow_sandbox_account_creation=true >> obp-api/src/main/resources/props/test.default.props + echo allow_sandbox_data_import=true >> obp-api/src/main/resources/props/test.default.props + echo sandbox_data_import_secret=change_me >> obp-api/src/main/resources/props/test.default.props + echo allow_account_deletion=true >> obp-api/src/main/resources/props/test.default.props + echo allowed_internal_redirect_urls = /,/oauth/authorize >> obp-api/src/main/resources/props/test.default.props + echo transactionRequests_enabled=true >> obp-api/src/main/resources/props/test.default.props + echo transactionRequests_supported_types=SEPA,SANDBOX_TAN,FREE_FORM,COUNTERPARTY,ACCOUNT,SIMPLE >> obp-api/src/main/resources/props/test.default.props + echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo openredirects.hostname.whitlelist=http://127.0.0.1,http://localhost >> obp-api/src/main/resources/props/test.default.props + echo remotedata.secret = foobarbaz >> obp-api/src/main/resources/props/test.default.props + echo allow_public_views=true >> obp-api/src/main/resources/props/test.default.props + + echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo ACCOUNT_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo SEPA_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo FREE_FORM_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo COUNTERPARTY_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo SEPA_CREDIT_TRANSFERS_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + + echo allow_oauth2_login=true >> obp-api/src/main/resources/props/test.default.props + echo oauth2.jwk_set.url=https://www.googleapis.com/oauth2/v3/certs >> obp-api/src/main/resources/props/test.default.props + + echo ResetPasswordUrlEnabled=true >> obp-api/src/main/resources/props/test.default.props + + echo consents.allowed=true >> obp-api/src/main/resources/props/test.default.props + MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod + + - name: Save .war artifact + run: | + mkdir -p ./push + cp obp-api/target/obp-api-1.*.war ./push/ + - uses: actions/upload-artifact@v4 + with: + name: ${{ github.sha }} + path: push/ + + - name: Build the Docker image + run: | + echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin docker.io + docker build . --file .github/Dockerfile_PreBuild --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/} + docker build . --file .github/Dockerfile_PreBuild_OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC + docker push docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }} --all-tags + echo docker done + + - uses: sigstore/cosign-installer@main + + - name: Write signing key to disk (only needed for `cosign sign --key`) + run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key + + - name: Sign container image + run: | + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/} + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA + env: + COSIGN_PASSWORD: "${{secrets.COSIGN_PASSWORD}}" + + + diff --git a/.github/workflows/run_trivy.yml b/.github/workflows/run_trivy.yml new file mode 100644 index 000000000..4636bd311 --- /dev/null +++ b/.github/workflows/run_trivy.yml @@ -0,0 +1,54 @@ +name: scan container image + +on: + workflow_run: + workflows: + - Build and publish container develop + - Build and publish container non develop + types: + - completed +env: + ## Sets environment variable + DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} + DOCKER_HUB_REPOSITORY: obp-api + + +jobs: + build: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + + steps: + - uses: actions/checkout@v4 + - id: trivy-db + name: Check trivy db sha + env: + GH_TOKEN: ${{ github.token }} + run: | + endpoint='/orgs/aquasecurity/packages/container/trivy-db/versions' + headers='Accept: application/vnd.github+json' + jqFilter='.[] | select(.metadata.container.tags[] | contains("latest")) | .name | sub("sha256:";"")' + sha=$(gh api -H "${headers}" "${endpoint}" | jq --raw-output "${jqFilter}") + echo "Trivy DB sha256:${sha}" + echo "::set-output name=sha::${sha}" + - uses: actions/cache@v4 + with: + path: .trivy + key: ${{ runner.os }}-trivy-db-${{ steps.trivy-db.outputs.sha }} + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@master + with: + image-ref: 'docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${{ github.sha }}' + format: 'template' + template: '@/contrib/sarif.tpl' + output: 'trivy-results.sarif' + security-checks: 'vuln' + severity: 'CRITICAL,HIGH' + timeout: '30m' + cache-dir: .trivy + - name: Fix .trivy permissions + run: sudo chown -R $(stat . -c %u:%g) .trivy + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'trivy-results.sarif' \ No newline at end of file From 9e6cc0fb871619c9bd611c9afa621afd514e8de6 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 6 Jan 2026 12:16:57 +0100 Subject: [PATCH 29/48] docfix/tweaked the default port for http4s --- README.md | 2 +- obp-api/src/main/resources/props/sample.props.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6d92e9c2b..33e7df4c4 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ MAVEN_OPTS="-Xms3G -Xmx6G -XX:MaxMetaspaceSize=2G" mvn -pl obp-http4s-runner -am java -jar obp-http4s-runner/target/obp-http4s-runner.jar ``` -The http4s server binds to `http4s.host` / `http4s.port` as configured in your props file (defaults are `127.0.0.1` and `8181`). +The http4s server binds to `http4s.host` / `http4s.port` as configured in your props file (defaults are `127.0.0.1` and `8086`). ### ZED IDE Setup diff --git a/obp-api/src/main/resources/props/sample.props.template b/obp-api/src/main/resources/props/sample.props.template index 29e80e27b..d181a5a1f 100644 --- a/obp-api/src/main/resources/props/sample.props.template +++ b/obp-api/src/main/resources/props/sample.props.template @@ -1691,6 +1691,6 @@ securelogging_mask_email=true ############################################ # Host and port for http4s server (used by bootstrap.http4s.Http4sServer) -# Defaults (if not set) are 127.0.0.1 and 8181 +# Defaults (if not set) are 127.0.0.1 and 8086 http4s.host=127.0.0.1 http4s.port=8086 \ No newline at end of file From 886bbf04f6e26f4ee3e878df5938c28871c862a7 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 6 Jan 2026 12:20:39 +0100 Subject: [PATCH 30/48] refactor/code clean --- obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala b/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala index 8207e7268..7a2a42c1c 100644 --- a/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala +++ b/obp-api/src/main/scala/bootstrap/http4s/Http4sServer.scala @@ -17,8 +17,7 @@ object Http4sServer extends IOApp { val port = APIUtil.getPropsAsIntValue("http4s.port",8086) val host = APIUtil.getPropsValue("http4s.host","127.0.0.1") - val services: Kleisli[({type λ[β$0$] = OptionT[IO, β$0$]})#λ, Request[IO], Response[IO]] = - code.api.v7_0_0.Http4s700.wrappedRoutesV700Services + val services: HttpRoutes[IO] = code.api.v7_0_0.Http4s700.wrappedRoutesV700Services val httpApp: Kleisli[IO, Request[IO], Response[IO]] = (services).orNotFound From e5dd7c4481f3d243dd05d30a76a398e242f60659 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Tue, 6 Jan 2026 15:47:38 +0100 Subject: [PATCH 31/48] flushall build and run runs http4s as well --- flushall_build_and_run.sh | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/flushall_build_and_run.sh b/flushall_build_and_run.sh index 833442508..6708a9ed1 100755 --- a/flushall_build_and_run.sh +++ b/flushall_build_and_run.sh @@ -1,10 +1,13 @@ #!/bin/bash -# Script to flush Redis, build the project, and run Jetty +# Script to flush Redis, build the project, and run both Jetty and http4s servers # # This script should be run from the OBP-API root directory: # cd /path/to/OBP-API # ./flushall_build_and_run.sh +# +# The http4s server will run in the background on port 8081 +# The Jetty server will run in the foreground on port 8080 set -e # Exit on error @@ -27,4 +30,29 @@ echo "==========================================" echo "Building and running with Maven..." echo "==========================================" export MAVEN_OPTS="-Xss128m --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED" -mvn install -pl .,obp-commons && mvn jetty:run -pl obp-api +mvn install -pl .,obp-commons + +echo "" +echo "==========================================" +echo "Building http4s runner..." +echo "==========================================" +export MAVEN_OPTS="-Xms3G -Xmx6G -XX:MaxMetaspaceSize=2G" +mvn -pl obp-http4s-runner -am clean package -DskipTests=true -Dmaven.test.skip=true + +echo "" +echo "==========================================" +echo "Starting http4s server in background..." +echo "==========================================" +java -jar obp-http4s-runner/target/obp-http4s-runner.jar > http4s-server.log 2>&1 & +HTTP4S_PID=$! +echo "http4s server started with PID: $HTTP4S_PID (port 8081)" +echo "Logs are being written to: http4s-server.log" +echo "" +echo "To stop http4s server later: kill $HTTP4S_PID" +echo "" + +echo "==========================================" +echo "Starting Jetty server (foreground)..." +echo "==========================================" +export MAVEN_OPTS="-Xss128m --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED" +mvn jetty:run -pl obp-api From b9ca1591f4787cb0be5a77446e5bc9e26b4814fe Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 6 Jan 2026 16:54:07 +0100 Subject: [PATCH 32/48] test/fixed failed tests --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 1 + .../src/main/scala/code/api/v6_0_0/APIMethods600.scala | 2 +- .../test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala | 8 +++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 4c17086c1..0a5110ebe 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -84,6 +84,7 @@ object ErrorMessages { val FXCurrencyCodeCombinationsNotSupported = "OBP-10004: ISO Currency code combination not supported for FX. Please modify the FROM_CURRENCY_CODE or TO_CURRENCY_CODE. " val InvalidDateFormat = "OBP-10005: Invalid Date Format. Could not convert value to a Date." val InvalidCurrency = "OBP-10006: Invalid Currency Value." + val InvalidCacheNamespaceId = "OBP-10123: Invalid namespace_id." val IncorrectRoleName = "OBP-10007: Incorrect Role name:" val CouldNotTransformJsonToInternalModel = "OBP-10008: Could not transform Json to internal model." val CountNotSaveOrUpdateResource = "OBP-10009: Could not save or update resource." diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 3f8a0d05e..b5b2c15b3 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -635,7 +635,7 @@ trait APIMethods600 { } namespaceId = postJson.namespace_id _ <- Helper.booleanToFuture( - s"Invalid namespace_id: $namespaceId. Valid values: ${Constant.ALL_CACHE_NAMESPACES.mkString(", ")}", + s"$InvalidCacheNamespaceId $namespaceId. Valid values: ${Constant.ALL_CACHE_NAMESPACES.mkString(", ")}", 400, callContext )(Constant.ALL_CACHE_NAMESPACES.contains(namespaceId)) diff --git a/obp-api/src/test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala index 690464e06..4a446b032 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/LogCacheEndpointTest.scala @@ -1,7 +1,7 @@ package code.api.v5_1_0 import code.api.util.APIUtil.OAuth._ -import code.api.util.ApiRole.CanGetSystemLogCacheAll +import code.api.util.ApiRole.{CanGetSystemLogCacheAll,CanGetSystemLogCacheInfo} import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn} import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0 import code.entitlement.Entitlement @@ -41,7 +41,9 @@ class LogCacheEndpointTest extends V510ServerSetup { val response = makeGetRequest(request) Then("error should be " + UserHasMissingRoles + CanGetSystemLogCacheAll) response.code should equal(403) - response.body.extract[ErrorMessage].message should be(UserHasMissingRoles + CanGetSystemLogCacheAll) + response.body.extract[ErrorMessage].message contains (UserHasMissingRoles) shouldBe (true) + response.body.extract[ErrorMessage].message contains CanGetSystemLogCacheInfo.toString() shouldBe (true) + response.body.extract[ErrorMessage].message contains CanGetSystemLogCacheAll.toString() shouldBe (true) } } @@ -129,7 +131,7 @@ class LogCacheEndpointTest extends V510ServerSetup { val response = makeGetRequest(request) Then("We should get a not found response since endpoint does not exist") - response.code should equal(404) + response.code should equal(400) val json = response.body.extract[JObject] And("The response should contain the correct error message") From 17f9677f1df0cd3f2ae665f11ecfbf694f6a7c1e Mon Sep 17 00:00:00 2001 From: simonredfern Date: Tue, 6 Jan 2026 23:46:35 +0100 Subject: [PATCH 33/48] flushall_build_and_run only liftweb run once again --- flushall_build_and_run.sh | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/flushall_build_and_run.sh b/flushall_build_and_run.sh index 6708a9ed1..833442508 100755 --- a/flushall_build_and_run.sh +++ b/flushall_build_and_run.sh @@ -1,13 +1,10 @@ #!/bin/bash -# Script to flush Redis, build the project, and run both Jetty and http4s servers +# Script to flush Redis, build the project, and run Jetty # # This script should be run from the OBP-API root directory: # cd /path/to/OBP-API # ./flushall_build_and_run.sh -# -# The http4s server will run in the background on port 8081 -# The Jetty server will run in the foreground on port 8080 set -e # Exit on error @@ -30,29 +27,4 @@ echo "==========================================" echo "Building and running with Maven..." echo "==========================================" export MAVEN_OPTS="-Xss128m --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED" -mvn install -pl .,obp-commons - -echo "" -echo "==========================================" -echo "Building http4s runner..." -echo "==========================================" -export MAVEN_OPTS="-Xms3G -Xmx6G -XX:MaxMetaspaceSize=2G" -mvn -pl obp-http4s-runner -am clean package -DskipTests=true -Dmaven.test.skip=true - -echo "" -echo "==========================================" -echo "Starting http4s server in background..." -echo "==========================================" -java -jar obp-http4s-runner/target/obp-http4s-runner.jar > http4s-server.log 2>&1 & -HTTP4S_PID=$! -echo "http4s server started with PID: $HTTP4S_PID (port 8081)" -echo "Logs are being written to: http4s-server.log" -echo "" -echo "To stop http4s server later: kill $HTTP4S_PID" -echo "" - -echo "==========================================" -echo "Starting Jetty server (foreground)..." -echo "==========================================" -export MAVEN_OPTS="-Xss128m --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED" -mvn jetty:run -pl obp-api +mvn install -pl .,obp-commons && mvn jetty:run -pl obp-api From 4fe67750298b708961fb7c1c8d0f333632fa5b02 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Sun, 11 Jan 2026 23:00:00 +0100 Subject: [PATCH 34/48] CanGetMethodRoutingNames --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 5 +++++ obp-api/src/main/scala/code/api/util/ApiRole.scala | 3 +++ obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala | 5 ++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 381b0c283..11ee5094c 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -1635,6 +1635,11 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ var errorResponseBodies: List[String], // Possible error responses tags: List[ResourceDocTag], var roles: Option[List[ApiRole]] = None, + // IMPORTANT: Roles declared here are AUTOMATICALLY CHECKED at runtime! + // When roles specified, framework automatically: 1) Validates user authentication, + // 2) Checks user has at least one of specified roles, 3) Performs checks in wrappedWithAuthCheck() + // No manual hasEntitlement() call needed in endpoint body - handled automatically! + // To disable: call .disableAutoValidateRoles() on ResourceDoc isFeatured: Boolean = false, specialInstructions: Option[String] = None, var specifiedUrl: Option[String] = None, // A derived value: Contains the called version (added at run time). See the resource doc for resource doc! diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index 9c7a990be..abbe92613 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -1003,6 +1003,9 @@ object ApiRole extends MdcLoggable{ case class CanGetAllConnectorMethods(requiresBankId: Boolean = false) extends ApiRole lazy val canGetAllConnectorMethods = CanGetAllConnectorMethods() + case class CanGetConnectorMethodNames(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetConnectorMethodNames = CanGetConnectorMethodNames() + case class CanCreateDynamicResourceDoc(requiresBankId: Boolean = false) extends ApiRole lazy val canCreateDynamicResourceDoc = CanCreateDynamicResourceDoc() diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index b5b2c15b3..14066eb81 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -1648,7 +1648,7 @@ trait APIMethods600 { | |${userAuthenticationMessage(true)} | - |CanGetMethodRoutings entitlement is required. + |CanGetConnectorMethodNames entitlement is required. | """.stripMargin, EmptyBody, @@ -1659,7 +1659,7 @@ trait APIMethods600 { UnknownError ), List(apiTagSystem, apiTagMethodRouting, apiTagApi), - Some(List(canGetMethodRoutings)) + Some(List(canGetConnectorMethodNames)) ) lazy val getConnectorMethodNames: OBPEndpoint = { @@ -1667,7 +1667,6 @@ trait APIMethods600 { cc => implicit val ec = EndpointContext(Some(cc)) for { (Full(u), callContext) <- authenticatedAccess(cc) - _ <- NewStyle.function.hasEntitlement("", u.userId, canGetMethodRoutings, callContext) // Fetch connector method names with caching methodNames <- Future { /** From 8698c8c0b50323db4ed65041768b65fc28ac013e Mon Sep 17 00:00:00 2001 From: simonredfern Date: Sun, 11 Jan 2026 23:24:31 +0100 Subject: [PATCH 35/48] Changed role name to canGetSystemConnectorMethodNames --- .../main/scala/code/api/util/ApiRole.scala | 128 +++++++++--------- .../scala/code/api/v6_0_0/APIMethods600.scala | 6 +- 2 files changed, 67 insertions(+), 67 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala index abbe92613..7a107307e 100644 --- a/obp-api/src/main/scala/code/api/util/ApiRole.scala +++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala @@ -86,19 +86,19 @@ object ApiRole extends MdcLoggable{ case class CanGetCustomersAtAllBanks(requiresBankId: Boolean = false) extends ApiRole lazy val canGetCustomersAtAllBanks = CanGetCustomersAtAllBanks() - + case class CanGetCustomersMinimalAtAllBanks(requiresBankId: Boolean = false) extends ApiRole lazy val canGetCustomersMinimalAtAllBanks = CanGetCustomersMinimalAtAllBanks() - + case class CanGetCustomersAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canGetCustomersAtOneBank = CanGetCustomersAtOneBank() - + case class CanGetCustomersMinimalAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canGetCustomersMinimalAtOneBank = CanGetCustomersMinimalAtOneBank() - + case class CanGetCustomerOverview(requiresBankId: Boolean = true) extends ApiRole lazy val canGetCustomerOverview = CanGetCustomerOverview() - + case class CanGetCustomerOverviewFlat(requiresBankId: Boolean = true) extends ApiRole lazy val canGetCustomerOverviewFlat = CanGetCustomerOverviewFlat() @@ -124,10 +124,10 @@ object ApiRole extends MdcLoggable{ // ALL case class CanGetSystemLogCacheAll(requiresBankId: Boolean = false) extends ApiRole lazy val canGetSystemLogCacheAll = CanGetSystemLogCacheAll() - + case class CanUpdateAgentStatusAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canUpdateAgentStatusAtAnyBank = CanUpdateAgentStatusAtAnyBank() - + case class CanUpdateAgentStatusAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateAgentStatusAtOneBank = CanUpdateAgentStatusAtOneBank() @@ -136,10 +136,10 @@ object ApiRole extends MdcLoggable{ case class CanUpdateCustomerNumber(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateCustomerNumber = CanUpdateCustomerNumber() - + case class CanUpdateCustomerMobilePhoneNumber(requiresBankId: Boolean = true) extends ApiRole - lazy val canUpdateCustomerMobilePhoneNumber = CanUpdateCustomerMobilePhoneNumber() - + lazy val canUpdateCustomerMobilePhoneNumber = CanUpdateCustomerMobilePhoneNumber() + case class CanUpdateCustomerIdentity(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateCustomerIdentity = CanUpdateCustomerIdentity() @@ -160,28 +160,28 @@ object ApiRole extends MdcLoggable{ case class CanCreateCustomerAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canCreateCustomerAtAnyBank = CanCreateCustomerAtAnyBank() - + case class CanGetCorrelatedUsersInfo(requiresBankId: Boolean = true) extends ApiRole - lazy val canGetCorrelatedUsersInfo = CanGetCorrelatedUsersInfo() - + lazy val canGetCorrelatedUsersInfo = CanGetCorrelatedUsersInfo() + case class CanGetCorrelatedUsersInfoAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canGetCorrelatedUsersInfoAtAnyBank = CanGetCorrelatedUsersInfoAtAnyBank() case class CanCreateUserCustomerLink(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateUserCustomerLink = CanCreateUserCustomerLink() - + case class CanDeleteUserCustomerLink(requiresBankId: Boolean = true) extends ApiRole lazy val canDeleteUserCustomerLink = CanDeleteUserCustomerLink() - + case class CanGetUserCustomerLink(requiresBankId: Boolean = true) extends ApiRole lazy val canGetUserCustomerLink = CanGetUserCustomerLink() case class CanCreateUserCustomerLinkAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canCreateUserCustomerLinkAtAnyBank = CanCreateUserCustomerLinkAtAnyBank() - + case class CanGetUserCustomerLinkAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canGetUserCustomerLinkAtAnyBank = CanGetUserCustomerLinkAtAnyBank() - + case class CanDeleteUserCustomerLinkAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteUserCustomerLinkAtAnyBank = CanDeleteUserCustomerLinkAtAnyBank() @@ -193,10 +193,10 @@ object ApiRole extends MdcLoggable{ case class CanCreateAccountAttributeAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateAccountAttributeAtOneBank = CanCreateAccountAttributeAtOneBank() - + case class CanUpdateAccountAttribute(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateAccountAttribute = CanUpdateAccountAttribute() - + case class CanGetAnyUser (requiresBankId: Boolean = false) extends ApiRole lazy val canGetAnyUser = CanGetAnyUser() @@ -226,10 +226,10 @@ object ApiRole extends MdcLoggable{ case class CanCreateEntitlementAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateEntitlementAtOneBank = CanCreateEntitlementAtOneBank() - + case class CanCreateSystemViewPermission(requiresBankId: Boolean = false) extends ApiRole lazy val canCreateSystemViewPermission = CanCreateSystemViewPermission() - + case class CanDeleteSystemViewPermission(requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteSystemViewPermission = CanDeleteSystemViewPermission() @@ -305,16 +305,16 @@ object ApiRole extends MdcLoggable{ case class CanGetCustomerAccountLink(requiresBankId: Boolean = true) extends ApiRole lazy val canGetCustomerAccountLink = CanGetCustomerAccountLink() - + case class CanGetCustomerAccountLinks(requiresBankId: Boolean = true) extends ApiRole lazy val canGetCustomerAccountLinks = CanGetCustomerAccountLinks() - + case class CanCreateBranch(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateBranch = CanCreateBranch() case class CanUpdateBranch(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateBranch = CanUpdateBranch() - + case class CanCreateBranchAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canCreateBranchAtAnyBank = CanCreateBranchAtAnyBank() @@ -325,14 +325,14 @@ object ApiRole extends MdcLoggable{ lazy val canDeleteBranchAtAnyBank = CanDeleteBranchAtAnyBank() case class CanCreateAtm(requiresBankId: Boolean = true) extends ApiRole - lazy val canCreateAtm = CanCreateAtm() - + lazy val canCreateAtm = CanCreateAtm() + case class CanDeleteAtm(requiresBankId: Boolean = true) extends ApiRole lazy val canDeleteAtm = CanDeleteAtm() case class CanDeleteAtmAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteAtmAtAnyBank = CanDeleteAtmAtAnyBank() - + case class CanUpdateAtm(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateAtm = CanUpdateAtm() @@ -344,22 +344,22 @@ object ApiRole extends MdcLoggable{ case class CanCreateCounterparty(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateCounterparty = CanCreateCounterparty() - + case class CanCreateCounterpartyAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canCreateCounterpartyAtAnyBank = CanCreateCounterpartyAtAnyBank() case class CanDeleteCounterparty(requiresBankId: Boolean = true) extends ApiRole lazy val canDeleteCounterparty = CanDeleteCounterparty() - + case class CanDeleteCounterpartyAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteCounterpartyAtAnyBank = CanDeleteCounterpartyAtAnyBank() - + case class CanGetCounterparty(requiresBankId: Boolean = true) extends ApiRole - lazy val canGetCounterparty = CanGetCounterparty() - + lazy val canGetCounterparty = CanGetCounterparty() + case class CanGetCounterpartiesAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canGetCounterpartiesAtAnyBank = CanGetCounterpartiesAtAnyBank() - + case class CanGetCounterparties(requiresBankId: Boolean = true) extends ApiRole lazy val canGetCounterparties = CanGetCounterparties() @@ -368,10 +368,10 @@ object ApiRole extends MdcLoggable{ case class CanGetAllApiCollections(requiresBankId: Boolean = false) extends ApiRole lazy val canGetAllApiCollections = CanGetAllApiCollections() - + case class CanGetCounterpartyAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canGetCounterpartyAtAnyBank = CanGetCounterpartyAtAnyBank() - + case class CanCreateProduct(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateProduct = CanCreateProduct() @@ -395,7 +395,7 @@ object ApiRole extends MdcLoggable{ case class CanReadMetrics (requiresBankId: Boolean = false) extends ApiRole lazy val canReadMetrics = CanReadMetrics() - + case class CanGetMetricsAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canGetMetricsAtOneBank = CanGetMetricsAtOneBank() @@ -419,19 +419,19 @@ object ApiRole extends MdcLoggable{ case class CanDeleteCacheKey(requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteCacheKey = CanDeleteCacheKey() lazy val canGetConfig = CanGetConfig() - + case class CanGetAdapterInfo(requiresBankId: Boolean = false) extends ApiRole lazy val canGetAdapterInfo = CanGetAdapterInfo() - + case class CanGetAdapterInfoAtOneBank(requiresBankId: Boolean = false) extends ApiRole lazy val canGetAdapterInfoAtOneBank = CanGetAdapterInfoAtOneBank() - + case class CanGetDatabaseInfo(requiresBankId: Boolean = false) extends ApiRole lazy val canGetDatabaseInfo = CanGetDatabaseInfo() - + case class CanGetMigrations(requiresBankId: Boolean = false) extends ApiRole lazy val canGetMigrations = CanGetMigrations() - + case class CanGetCallContext(requiresBankId: Boolean = false) extends ApiRole lazy val canGetCallContext = CanGetCallContext() @@ -446,10 +446,10 @@ object ApiRole extends MdcLoggable{ case class CanUseAccountFirehoseAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canUseAccountFirehoseAtAnyBank = CanUseAccountFirehoseAtAnyBank() - + case class CanUseAccountFirehose(requiresBankId: Boolean = true) extends ApiRole lazy val canUseAccountFirehose = CanUseAccountFirehose() - + case class CanUseCustomerFirehoseAtAnyBank(requiresBankId: Boolean = false) extends ApiRole lazy val canUseCustomerFirehoseAtAnyBank = CanUseCustomerFirehoseAtAnyBank() @@ -467,38 +467,38 @@ object ApiRole extends MdcLoggable{ case class CanUnlockUser (requiresBankId: Boolean = false) extends ApiRole lazy val canUnlockUser = CanUnlockUser() - + case class CanLockUser (requiresBankId: Boolean = false) extends ApiRole lazy val canLockUser = CanLockUser() - + case class CanDeleteUser (requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteUser = CanDeleteUser() case class CanValidateUser (requiresBankId: Boolean = false) extends ApiRole lazy val canValidateUser = CanValidateUser() - + case class CanGetUsersWithAttributes (requiresBankId: Boolean = false) extends ApiRole lazy val canGetUsersWithAttributes = CanGetUsersWithAttributes() - + case class CanCreateNonPersonalUserAttribute (requiresBankId: Boolean = false) extends ApiRole lazy val canCreateNonPersonalUserAttribute = CanCreateNonPersonalUserAttribute() - + case class CanGetNonPersonalUserAttributes (requiresBankId: Boolean = false) extends ApiRole lazy val canGetNonPersonalUserAttributes = CanGetNonPersonalUserAttributes() - + case class CanDeleteNonPersonalUserAttribute (requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteNonPersonalUserAttribute = CanDeleteNonPersonalUserAttribute() // v6.0.0 User Attribute roles (consistent naming - "user attributes" means non-personal) case class CanCreateUserAttribute (requiresBankId: Boolean = false) extends ApiRole lazy val canCreateUserAttribute = CanCreateUserAttribute() - + case class CanGetUserAttributes (requiresBankId: Boolean = false) extends ApiRole lazy val canGetUserAttributes = CanGetUserAttributes() - + case class CanUpdateUserAttribute (requiresBankId: Boolean = false) extends ApiRole lazy val canUpdateUserAttribute = CanUpdateUserAttribute() - + case class CanDeleteUserAttribute (requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteUserAttribute = CanDeleteUserAttribute() @@ -510,7 +510,7 @@ object ApiRole extends MdcLoggable{ case class CanCreateRateLimits(requiresBankId: Boolean = false) extends ApiRole lazy val canCreateRateLimits = CanCreateRateLimits() - + case class CanDeleteRateLimits(requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteRateLimits = CanDeleteRateLimits() @@ -1003,8 +1003,8 @@ object ApiRole extends MdcLoggable{ case class CanGetAllConnectorMethods(requiresBankId: Boolean = false) extends ApiRole lazy val canGetAllConnectorMethods = CanGetAllConnectorMethods() - case class CanGetConnectorMethodNames(requiresBankId: Boolean = false) extends ApiRole - lazy val canGetConnectorMethodNames = CanGetConnectorMethodNames() + case class CanGetSystemConnectorMethodNames(requiresBankId: Boolean = false) extends ApiRole + lazy val canGetSystemConnectorMethodNames = CanGetSystemConnectorMethodNames() case class CanCreateDynamicResourceDoc(requiresBankId: Boolean = false) extends ApiRole lazy val canCreateDynamicResourceDoc = CanCreateDynamicResourceDoc() @@ -1173,17 +1173,17 @@ object ApiRole extends MdcLoggable{ lazy val canCreateGroupAtAllBanks = CanCreateGroupAtAllBanks() case class CanCreateGroupAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canCreateGroupAtOneBank = CanCreateGroupAtOneBank() - + case class CanUpdateGroupAtAllBanks(requiresBankId: Boolean = false) extends ApiRole lazy val canUpdateGroupAtAllBanks = CanUpdateGroupAtAllBanks() case class CanUpdateGroupAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canUpdateGroupAtOneBank = CanUpdateGroupAtOneBank() - + case class CanDeleteGroupAtAllBanks(requiresBankId: Boolean = false) extends ApiRole lazy val canDeleteGroupAtAllBanks = CanDeleteGroupAtAllBanks() case class CanDeleteGroupAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canDeleteGroupAtOneBank = CanDeleteGroupAtOneBank() - + case class CanGetGroupsAtAllBanks(requiresBankId: Boolean = false) extends ApiRole lazy val canGetGroupsAtAllBanks = CanGetGroupsAtAllBanks() case class CanGetGroupsAtOneBank(requiresBankId: Boolean = true) extends ApiRole @@ -1194,12 +1194,12 @@ object ApiRole extends MdcLoggable{ lazy val canAddUserToGroupAtAllBanks = CanAddUserToGroupAtAllBanks() case class CanAddUserToGroupAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canAddUserToGroupAtOneBank = CanAddUserToGroupAtOneBank() - + case class CanRemoveUserFromGroupAtAllBanks(requiresBankId: Boolean = false) extends ApiRole lazy val canRemoveUserFromGroupAtAllBanks = CanRemoveUserFromGroupAtAllBanks() case class CanRemoveUserFromGroupAtOneBank(requiresBankId: Boolean = true) extends ApiRole lazy val canRemoveUserFromGroupAtOneBank = CanRemoveUserFromGroupAtOneBank() - + case class CanGetUserGroupMembershipsAtAllBanks(requiresBankId: Boolean = false) extends ApiRole lazy val canGetUserGroupMembershipsAtAllBanks = CanGetUserGroupMembershipsAtAllBanks() case class CanGetUserGroupMembershipsAtOneBank(requiresBankId: Boolean = true) extends ApiRole @@ -1282,15 +1282,15 @@ object Util { "CanSetCallLimits", "CanDeleteRateLimits" ) - + val allowed = allowedPrefixes ::: allowedExistingNames source.collect { case obj: Defn.Object if obj.name.value == "ApiRole" => obj.collect { - case c: Defn.Class if allowed.exists(i => c.name.syntax.startsWith(i)) == true => + case c: Defn.Class if allowed.exists(i => c.name.syntax.startsWith(i)) == true => // OK - case c: Defn.Class if allowed.exists(i => c.name.syntax.startsWith(i)) == false => + case c: Defn.Class if allowed.exists(i => c.name.syntax.startsWith(i)) == false => println("INCORRECT - " + c) } } @@ -1300,4 +1300,4 @@ object Util { checkWrongDefinedNames } -} \ No newline at end of file +} diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 14066eb81..cd9b9aab0 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -1648,7 +1648,7 @@ trait APIMethods600 { | |${userAuthenticationMessage(true)} | - |CanGetConnectorMethodNames entitlement is required. + |CanGetSystemConnectorMethodNames entitlement is required. | """.stripMargin, EmptyBody, @@ -1658,8 +1658,8 @@ trait APIMethods600 { UserHasMissingRoles, UnknownError ), - List(apiTagSystem, apiTagMethodRouting, apiTagApi), - Some(List(canGetConnectorMethodNames)) + List(apiTagConnectorMethod, apiTagSystem, apiTagMethodRouting, apiTagApi), + Some(List(canGetSystemConnectorMethodNames)) ) lazy val getConnectorMethodNames: OBPEndpoint = { From 09e8c6c48f8ca3046a1bc7a633ff0a0bad49ce61 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Tue, 13 Jan 2026 14:21:55 +0100 Subject: [PATCH 36/48] Docfix: Fewer ABA examples part 1 --- .../scala/code/api/v6_0_0/APIMethods600.scala | 554 ++---------------- 1 file changed, 40 insertions(+), 514 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index cd9b9aab0..40ab1fc7d 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -5236,538 +5236,64 @@ trait APIMethods600 { ), examples = List( AbacRuleExampleJsonV600( - category = "User - Authenticated User", - title = "Check Email Domain", - code = "authenticatedUser.emailAddress.contains(\"@example.com\")", - description = "Verify that the authenticated user's email belongs to a specific domain" + category = "Access Control - Account Access", + title = "Branch Manager Internal Account Access", + code = "authenticatedUserAttributes.exists(a => a.name == \"branch\" && accountAttributes.exists(aa => aa.name == \"branch\" && a.value == aa.value)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(_.accountType == \"CURRENT\")", + description = "Allow GET access to current accounts only when user's branch matches account's branch" ), AbacRuleExampleJsonV600( - category = "User - Authenticated User", - title = "Check Authentication Provider", - code = "authenticatedUser.provider == \"obp\"", - description = "Verify the authentication provider is OBP" + category = "Access Control - Transaction Access", + title = "Internal Network High-Value Transaction Review", + code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"10.\"))) && authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"compliance_officer\") && transactionOpt.exists(_.amount > 10000)", + description = "Allow compliance officers on internal network to review high-value transactions over 10,000" ), AbacRuleExampleJsonV600( - category = "User - Authenticated User", - title = "Compare Authenticated to Target User", - code = "authenticatedUser.userId == userOpt.get.userId", - description = "Check if authenticated user matches the target user (unsafe - use exists instead)" + category = "Access Control - Customer Data", + title = "Regional Manager Customer Access via Mobile", + code = "authenticatedUserAttributes.exists(a => a.name == \"region\" && customerAttributes.exists(ca => ca.name == \"region\" && a.value == ca.value)) && callContext.exists(_.userAgent.exists(_.contains(\"Mobile\"))) && customerOpt.exists(_.relationshipStatus == \"ACTIVE\")", + description = "Allow regional managers to access active customers in their region when using mobile app" ), AbacRuleExampleJsonV600( - category = "User - Authenticated User", - title = "Check User Not Deleted", - code = "!authenticatedUser.isDeleted.getOrElse(false)", - description = "Verify the authenticated user is not marked as deleted" + category = "Access Control - Transaction Modification", + title = "Authorized Delegation Transaction Update", + code = "onBehalfOfUserOpt.exists(_.userId != authenticatedUser.userId) && onBehalfOfUserAttributes.exists(a => a.name == \"delegation_level\" && a.value == \"full\") && callContext.exists(_.verb.exists(_ == \"PUT\")) && transactionOpt.exists(t => t.amount < 5000)", + description = "Allow full delegation to update transactions under 5000 via PUT requests" ), AbacRuleExampleJsonV600( - category = "User Attributes - Authenticated User", - title = "Check Admin Role", - code = "authenticatedUserAttributes.exists(attr => attr.name == \"role\" && attr.value == \"admin\")", - description = "Check if authenticated user has admin role attribute" + category = "Access Control - Account Balance", + title = "Department Head Same-Department Account Read", + code = "authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"department_head\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance > 0)", + description = "Allow department heads to read account details for accounts in their department with positive balance" ), AbacRuleExampleJsonV600( - category = "User Attributes - Authenticated User", - title = "Check Department", - code = "authenticatedUserAttributes.find(_.name == \"department\").exists(_.value == \"finance\")", - description = "Check if authenticated user belongs to finance department" + category = "Access Control - Transaction Request Approval", + title = "Manager Internal Network Transaction Approval", + code = "authenticatedUserAttributes.exists(a => a.name == \"role\" && List(\"manager\", \"supervisor\").contains(a.value)) && callContext.exists(_.ipAddress.exists(ip => ip.startsWith(\"10.\") || ip.startsWith(\"192.168.\"))) && transactionRequestOpt.exists(tr => tr.status == \"PENDING\" && tr.charge.value.toDouble < 50000)", + description = "Allow managers/supervisors on internal network to approve pending transaction requests under 50,000" ), AbacRuleExampleJsonV600( - category = "User Attributes - Authenticated User", - title = "Check Multiple Roles", - code = "authenticatedUserAttributes.exists(attr => attr.name == \"role\" && List(\"admin\", \"manager\").contains(attr.value))", - description = "Check if authenticated user has admin or manager role" + category = "Access Control - Customer Onboarding", + title = "KYC Officer Customer Creation from Branch", + code = "authenticatedUserAttributes.exists(a => a.name == \"certification\" && a.value == \"kyc_certified\") && callContext.exists(_.verb.exists(_ == \"POST\")) && callContext.exists(_.ipAddress.exists(_.startsWith(\"10.20.\"))) && customerAttributes.exists(ca => ca.name == \"onboarding_status\" && ca.value == \"pending\")", + description = "Allow KYC certified officers to create customers via POST from branch network (10.20.x.x) when status is pending" ), AbacRuleExampleJsonV600( - category = "User Auth Context", - title = "Check Session Type", - code = "authenticatedUserAuthContext.exists(_.key == \"session_type\" && _.value == \"secure\")", - description = "Verify the session type is secure" + category = "Access Control - Cross-Border Transaction", + title = "International Team Foreign Currency Transaction", + code = "authenticatedUserAttributes.exists(a => a.name == \"team\" && a.value == \"international\") && callContext.exists(_.url.exists(_.contains(\"/transactions/\"))) && transactionOpt.exists(t => t.currency != \"USD\" && t.amount < 100000) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"international_enabled\" && aa.value == \"true\"))", + description = "Allow international team to access foreign currency transactions under 100k on international-enabled accounts" ), AbacRuleExampleJsonV600( - category = "User Auth Context", - title = "Check Auth Method", - code = "authenticatedUserAuthContext.exists(_.key == \"auth_method\" && _.value == \"certificate\")", - description = "Verify authentication was done via certificate" + category = "Access Control - Delegated Account Management", + title = "Assistant with Limited Delegation Account View", + code = "onBehalfOfUserOpt.isDefined && onBehalfOfUserAttributes.exists(a => a.name == \"role\" && a.value == \"executive\") && authenticatedUserAttributes.exists(a => a.name == \"assistant_of\" && onBehalfOfUserOpt.exists(u => a.value == u.userId)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"tier\" && List(\"gold\", \"platinum\").contains(aa.value)))", + description = "Allow assistants to view gold/platinum accounts via GET when acting on behalf of their assigned executive" ), AbacRuleExampleJsonV600( - category = "User - Delegation", - title = "Check Delegated User Email Domain", - code = "onBehalfOfUserOpt.exists(_.emailAddress.endsWith(\"@company.com\"))", - description = "Check if delegation user belongs to specific company domain" - ), - AbacRuleExampleJsonV600( - category = "User - Delegation", - title = "Check No Delegation or Self Delegation", - code = "onBehalfOfUserOpt.isEmpty || onBehalfOfUserOpt.get.userId == authenticatedUser.userId", - description = "Allow if no delegation or user delegating to themselves" - ), - AbacRuleExampleJsonV600( - category = "User - Delegation", - title = "Check Different User Delegation", - code = "onBehalfOfUserOpt.forall(_.userId != authenticatedUser.userId)", - description = "Check that delegation is to a different user (if present)" - ), - AbacRuleExampleJsonV600( - category = "User Attributes - Delegation", - title = "Check Delegation Level", - code = "onBehalfOfUserAttributes.exists(attr => attr.name == \"delegation_level\" && attr.value == \"full\")", - description = "Check if delegation has full permission level" - ), - AbacRuleExampleJsonV600( - category = "User Attributes - Delegation", - title = "Check Authorized Delegation", - code = "onBehalfOfUserAttributes.isEmpty || onBehalfOfUserAttributes.exists(_.name == \"authorized\")", - description = "Allow if no delegation attributes or has authorized attribute" - ), - AbacRuleExampleJsonV600( - category = "User - Target User", - title = "Check Self Access", - code = "userOpt.isDefined && userOpt.get.userId == authenticatedUser.userId", - description = "Check if target user is the authenticated user (self-access)" - ), - AbacRuleExampleJsonV600( - category = "User - Target User", - title = "Check Target User Provider", - code = "userOpt.exists(_.provider == \"obp\")", - description = "Check if target user is authenticated via OBP provider" - ), - AbacRuleExampleJsonV600( - category = "User - Target User", - title = "Check Target User Email Domain", - code = "userOpt.exists(_.emailAddress.endsWith(\"@trusted.com\"))", - description = "Check if target user belongs to trusted domain" - ), - AbacRuleExampleJsonV600( - category = "User - Target User", - title = "Check Target User Active", - code = "userOpt.forall(!_.isDeleted.getOrElse(false))", - description = "Ensure target user is not deleted (if present)" - ), - AbacRuleExampleJsonV600( - category = "User Attributes - Target User", - title = "Check Premium Account", - code = "userAttributes.exists(attr => attr.name == \"account_type\" && attr.value == \"premium\")", - description = "Check if target user has premium account type" - ), - AbacRuleExampleJsonV600( - category = "User Attributes - Target User", - title = "Check KYC Status", - code = "userAttributes.exists(attr => attr.name == \"kyc_status\" && attr.value == \"verified\")", - description = "Check if target user has verified KYC status" - ), - AbacRuleExampleJsonV600( - category = "User Attributes - Target User", - title = "Check User Tier Level", - code = "userAttributes.find(_.name == \"tier\").exists(_.value.toInt >= 2)", - description = "Check if user tier is 2 or higher" - ), - AbacRuleExampleJsonV600( - category = "Bank", - title = "Check Specific Bank ID", - code = "bankOpt.isDefined && bankOpt.get.bankId.value == \"gh.29.uk\"", - description = "Check if bank context is defined and matches specific bank ID" - ), - AbacRuleExampleJsonV600( - category = "Bank", - title = "Check Bank Name Contains Text", - code = "bankOpt.exists(_.fullName.contains(\"Community\"))", - description = "Check if bank full name contains specific text" - ), - AbacRuleExampleJsonV600( - category = "Bank", - title = "Check Bank Has HTTPS Website", - code = "bankOpt.exists(_.websiteUrl.contains(\"https://\"))", - description = "Check if bank website uses HTTPS" - ), - AbacRuleExampleJsonV600( - category = "Bank Attributes", - title = "Check Bank Region", - code = "bankAttributes.exists(attr => attr.name == \"region\" && attr.value == \"EU\")", - description = "Check if bank is in EU region" - ), - AbacRuleExampleJsonV600( - category = "Bank Attributes", - title = "Check Bank Certification", - code = "bankAttributes.exists(attr => attr.name == \"certified\" && attr.value == \"true\")", - description = "Check if bank has certification attribute" - ), - AbacRuleExampleJsonV600( - category = "Account", - title = "Check Minimum Balance", - code = "accountOpt.isDefined && accountOpt.get.balance > 1000", - description = "Check if account balance is above threshold" - ), - AbacRuleExampleJsonV600( - category = "Account", - title = "Check USD Account Balance", - code = "accountOpt.exists(acc => acc.currency == \"USD\" && acc.balance > 5000)", - description = "Check if USD account has balance above $5000" - ), - AbacRuleExampleJsonV600( - category = "Account", - title = "Check Account Type", - code = "accountOpt.exists(_.accountType == \"SAVINGS\")", - description = "Check if account is a savings account" - ), - AbacRuleExampleJsonV600( - category = "Account", - title = "Check Account Number Length", - code = "accountOpt.exists(_.number.length >= 10)", - description = "Check if account number has minimum length" - ), - AbacRuleExampleJsonV600( - category = "Account Attributes", - title = "Check Account Status", - code = "accountAttributes.exists(attr => attr.name == \"status\" && attr.value == \"active\")", - description = "Check if account has active status" - ), - AbacRuleExampleJsonV600( - category = "Account Attributes", - title = "Check Account Tier", - code = "accountAttributes.exists(attr => attr.name == \"account_tier\" && attr.value == \"gold\")", - description = "Check if account has gold tier" - ), - AbacRuleExampleJsonV600( - category = "Transaction", - title = "Check Transaction Amount Limit", - code = "transactionOpt.isDefined && transactionOpt.get.amount < 10000", - description = "Check if transaction amount is below limit" - ), - AbacRuleExampleJsonV600( - category = "Transaction", - title = "Check Transaction Type", - code = "transactionOpt.exists(_.transactionType.contains(\"TRANSFER\"))", - description = "Check if transaction is a transfer type" - ), - AbacRuleExampleJsonV600( - category = "Transaction", - title = "Check EUR Transaction Amount", - code = "transactionOpt.exists(t => t.currency == \"EUR\" && t.amount > 100)", - description = "Check if EUR transaction exceeds €100" - ), - AbacRuleExampleJsonV600( - category = "Transaction", - title = "Check Positive Balance After Transaction", - code = "transactionOpt.exists(_.balance > 0)", - description = "Check if balance remains positive after transaction" - ), - AbacRuleExampleJsonV600( - category = "Transaction Attributes", - title = "Check Transaction Category", - code = "transactionAttributes.exists(attr => attr.name == \"category\" && attr.value == \"business\")", - description = "Check if transaction is categorized as business" - ), - AbacRuleExampleJsonV600( - category = "Transaction Attributes", - title = "Check Transaction Not Flagged", - code = "!transactionAttributes.exists(attr => attr.name == \"flagged\" && attr.value == \"true\")", - description = "Check that transaction is not flagged" - ), - AbacRuleExampleJsonV600( - category = "Transaction Request", - title = "Check Pending Status", - code = "transactionRequestOpt.exists(_.status == \"PENDING\")", - description = "Check if transaction request is pending" - ), - AbacRuleExampleJsonV600( - category = "Transaction Request", - title = "Check SEPA Type", - code = "transactionRequestOpt.exists(_.type == \"SEPA\")", - description = "Check if transaction request is SEPA type" - ), - AbacRuleExampleJsonV600( - category = "Transaction Request", - title = "Check Same Bank", - code = "transactionRequestOpt.exists(_.this_bank_id.value == bankOpt.get.bankId.value)", - description = "Check if transaction request is for the same bank (unsafe - use exists)" - ), - AbacRuleExampleJsonV600( - category = "Transaction Request Attributes", - title = "Check High Priority", - code = "transactionRequestAttributes.exists(attr => attr.name == \"priority\" && attr.value == \"high\")", - description = "Check if transaction request has high priority" - ), - AbacRuleExampleJsonV600( - category = "Transaction Request Attributes", - title = "Check Mobile App Source", - code = "transactionRequestAttributes.exists(attr => attr.name == \"source\" && attr.value == \"mobile_app\")", - description = "Check if transaction request originated from mobile app" - ), - AbacRuleExampleJsonV600( - category = "Customer", - title = "Check Corporate Customer", - code = "customerOpt.exists(_.legalName.contains(\"Corp\"))", - description = "Check if customer legal name contains Corp" - ), - AbacRuleExampleJsonV600( - category = "Customer", - title = "Check Customer Email Matches User", - code = "customerOpt.isDefined && customerOpt.get.email == authenticatedUser.emailAddress", - description = "Check if customer email matches authenticated user" - ), - AbacRuleExampleJsonV600( - category = "Customer", - title = "Check Active Customer Relationship", - code = "customerOpt.exists(_.relationshipStatus == \"ACTIVE\")", - description = "Check if customer relationship is active" - ), - AbacRuleExampleJsonV600( - category = "Customer", - title = "Check Customer Has Mobile", - code = "customerOpt.exists(_.mobileNumber.nonEmpty)", - description = "Check if customer has mobile number on file" - ), - AbacRuleExampleJsonV600( - category = "Customer Attributes", - title = "Check Low Risk Customer", - code = "customerAttributes.exists(attr => attr.name == \"risk_level\" && attr.value == \"low\")", - description = "Check if customer has low risk level" - ), - AbacRuleExampleJsonV600( - category = "Customer Attributes", - title = "Check VIP Status", - code = "customerAttributes.exists(attr => attr.name == \"vip_status\" && attr.value == \"true\")", - description = "Check if customer has VIP status" - ), - AbacRuleExampleJsonV600( - category = "Call Context", - title = "Check Internal Network", - code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"192.168\")))", - description = "Check if request comes from internal network" - ), - AbacRuleExampleJsonV600( - category = "Call Context", - title = "Check GET Request", - code = "callContext.exists(_.verb.exists(_ == \"GET\"))", - description = "Check if request is GET method" - ), - AbacRuleExampleJsonV600( - category = "Call Context", - title = "Check URL Contains Pattern", - code = "callContext.exists(_.url.exists(_.contains(\"/accounts/\")))", - description = "Check if request URL contains accounts path" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - User Comparisons", - title = "Self Access Check", - code = "userOpt.exists(_.userId == authenticatedUser.userId)", - description = "Check if target user is the authenticated user" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - User Comparisons", - title = "Same Email Check", - code = "userOpt.exists(_.emailAddress == authenticatedUser.emailAddress)", - description = "Check if target user has same email as authenticated user" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - User Comparisons", - title = "Same Email Domain", - code = "userOpt.exists(u => authenticatedUser.emailAddress.split(\"@\")(1) == u.emailAddress.split(\"@\")(1))", - description = "Check if both users belong to same email domain" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - User Comparisons", - title = "Delegation Match", - code = "onBehalfOfUserOpt.isDefined && userOpt.isDefined && onBehalfOfUserOpt.get.userId == userOpt.get.userId", - description = "Check if delegation user matches target user" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - User Comparisons", - title = "Different User Access", - code = "userOpt.exists(_.userId != authenticatedUser.userId)", - description = "Check if accessing a different user's data" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Customer Comparisons", - title = "Customer Email Matches Auth User", - code = "customerOpt.exists(_.email == authenticatedUser.emailAddress)", - description = "Check if customer email matches authenticated user" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Customer Comparisons", - title = "Customer Email Matches Target User", - code = "customerOpt.isDefined && userOpt.isDefined && customerOpt.get.email == userOpt.get.emailAddress", - description = "Check if customer email matches target user email" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Customer Comparisons", - title = "Customer Name Contains User Name", - code = "customerOpt.exists(c => userOpt.exists(u => c.legalName.contains(u.name)))", - description = "Check if customer legal name contains user name" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Account/Transaction", - title = "Transaction Within Balance", - code = "transactionOpt.isDefined && accountOpt.isDefined && transactionOpt.get.amount < accountOpt.get.balance", - description = "Check if transaction amount is less than account balance" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Account/Transaction", - title = "Transaction Within 50% Balance", - code = "transactionOpt.exists(t => accountOpt.exists(a => t.amount <= a.balance * 0.5))", - description = "Check if transaction is within 50% of account balance" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Account/Transaction", - title = "Same Currency Check", - code = "transactionOpt.exists(t => accountOpt.exists(a => t.currency == a.currency))", - description = "Check if transaction and account have same currency" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Account/Transaction", - title = "Sufficient Funds After Transaction", - code = "transactionOpt.exists(t => accountOpt.exists(a => a.balance - t.amount >= 0))", - description = "Check if account will have sufficient funds after transaction" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Account/Transaction", - title = "Debit from Checking", - code = "transactionOpt.exists(t => accountOpt.exists(a => (a.accountType == \"CHECKING\" && t.transactionType.exists(_.contains(\"DEBIT\")))))", - description = "Check if debit transaction from checking account" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Bank/Account", - title = "Account Belongs to Bank", - code = "accountOpt.isDefined && bankOpt.isDefined && accountOpt.get.bankId == bankOpt.get.bankId.value", - description = "Check if account belongs to the bank" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Bank/Account", - title = "Account Currency Matches Bank Currency", - code = "accountOpt.exists(a => bankAttributes.exists(attr => attr.name == \"primary_currency\" && attr.value == a.currency))", - description = "Check if account currency matches bank's primary currency" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Transaction Request", - title = "Transaction Request for Account", - code = "transactionRequestOpt.exists(tr => accountOpt.exists(a => tr.this_account_id.value == a.accountId.value))", - description = "Check if transaction request is for this account" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Transaction Request", - title = "Transaction Request for Bank", - code = "transactionRequestOpt.exists(tr => bankOpt.exists(b => tr.this_bank_id.value == b.bankId.value))", - description = "Check if transaction request is for this bank" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Transaction Request", - title = "Transaction Amount Matches Charge", - code = "transactionOpt.isDefined && transactionRequestOpt.isDefined && transactionOpt.get.amount == transactionRequestOpt.get.charge.value.toDouble", - description = "Check if transaction amount matches request charge" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Attribute Comparisons", - title = "User and Account Same Tier", - code = "userAttributes.exists(ua => ua.name == \"tier\" && accountAttributes.exists(aa => aa.name == \"tier\" && ua.value == aa.value))", - description = "Check if user tier matches account tier" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Attribute Comparisons", - title = "Customer and Account Same Segment", - code = "customerAttributes.exists(ca => ca.name == \"segment\" && accountAttributes.exists(aa => aa.name == \"segment\" && ca.value == aa.value))", - description = "Check if customer segment matches account segment" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Attribute Comparisons", - title = "Auth User and Account Same Department", - code = "authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value))", - description = "Check if authenticated user department matches account department" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Attribute Comparisons", - title = "Transaction Risk Within User Tolerance", - code = "transactionAttributes.exists(ta => ta.name == \"risk_score\" && userAttributes.exists(ua => ua.name == \"risk_tolerance\" && ta.value.toInt <= ua.value.toInt))", - description = "Check if transaction risk is within user's tolerance" - ), - AbacRuleExampleJsonV600( - category = "Cross-Object - Attribute Comparisons", - title = "Bank and Customer Same Region", - code = "bankAttributes.exists(ba => ba.name == \"region\" && customerAttributes.exists(ca => ca.name == \"region\" && ba.value == ca.value))", - description = "Check if bank and customer are in same region" - ), - AbacRuleExampleJsonV600( - category = "Complex - Multi-Object", - title = "Bank Employee with Active Account", - code = "authenticatedUser.emailAddress.endsWith(\"@bank.com\") && accountOpt.exists(_.balance > 0) && bankOpt.exists(_.bankId.value == \"gh.29.uk\")", - description = "Check if bank employee accessing active account at specific bank" - ), - AbacRuleExampleJsonV600( - category = "Complex - Multi-Object", - title = "Manager Accessing Other User", - code = "authenticatedUserAttributes.exists(_.name == \"role\" && _.value == \"manager\") && userOpt.exists(_.userId != authenticatedUser.userId)", - description = "Check if manager is accessing another user's data" - ), - AbacRuleExampleJsonV600( - category = "Complex - Multi-Object", - title = "Self or Authorized Delegation with Balance", - code = "(onBehalfOfUserOpt.isEmpty || onBehalfOfUserOpt.get.userId == authenticatedUser.userId) && accountOpt.exists(_.balance > 1000)", - description = "Check if self-access or authorized delegation with minimum balance" - ), - AbacRuleExampleJsonV600( - category = "Complex - Multi-Object", - title = "Verified User with Optional Delegation", - code = "userAttributes.exists(_.name == \"kyc_status\" && _.value == \"verified\") && (onBehalfOfUserOpt.isEmpty || onBehalfOfUserAttributes.exists(_.name == \"authorized\"))", - description = "Check if user is KYC verified and delegation is authorized (if present)" - ), - AbacRuleExampleJsonV600( - category = "Complex - Multi-Object", - title = "VIP Customer with Premium Account", - code = "customerAttributes.exists(_.name == \"vip_status\" && _.value == \"true\") && accountAttributes.exists(_.name == \"account_tier\" && _.value == \"premium\")", - description = "Check if VIP customer has premium account" - ), - AbacRuleExampleJsonV600( - category = "Complex - Chained Validation", - title = "User-Customer-Account-Transaction Chain", - code = "userOpt.exists(u => customerOpt.exists(c => c.email == u.emailAddress && accountOpt.exists(a => transactionOpt.exists(t => t.accountId.value == a.accountId.value))))", - description = "Validate complete chain from user to customer to account to transaction" - ), - AbacRuleExampleJsonV600( - category = "Complex - Chained Validation", - title = "Bank-Account-Transaction Request Chain", - code = "bankOpt.exists(b => accountOpt.exists(a => a.bankId == b.bankId.value && transactionRequestOpt.exists(tr => tr.this_account_id.value == a.accountId.value)))", - description = "Validate bank owns account and transaction request is for that account" - ), - AbacRuleExampleJsonV600( - category = "Complex - Aggregation", - title = "Matching Attributes", - code = "authenticatedUserAttributes.exists(aua => userAttributes.exists(ua => aua.name == ua.name && aua.value == ua.value))", - description = "Check if authenticated user and target user share any matching attributes" - ), - AbacRuleExampleJsonV600( - category = "Complex - Aggregation", - title = "Allowed Transaction Attributes", - code = "transactionAttributes.forall(ta => accountAttributes.exists(aa => aa.name == \"allowed_transaction_\" + ta.name))", - description = "Check if all transaction attributes are allowed for this account" - ), - AbacRuleExampleJsonV600( - category = "Business Logic - Loan Approval", - title = "Credit Score and Balance Check", - code = "customerAttributes.exists(ca => ca.name == \"credit_score\" && ca.value.toInt > 650) && accountOpt.exists(_.balance > 5000)", - description = "Check if customer has good credit score and sufficient balance for loan" - ), - AbacRuleExampleJsonV600( - category = "Business Logic - Wire Transfer", - title = "Wire Transfer Authorization", - code = "transactionOpt.exists(t => t.amount < 100000 && t.transactionType.exists(_.contains(\"WIRE\"))) && authenticatedUserAttributes.exists(_.name == \"wire_authorized\")", - description = "Check if wire transfer is under limit and user is authorized" - ), - AbacRuleExampleJsonV600( - category = "Business Logic - Account Closure", - title = "Self-Service or Manager Account Closure", - code = "accountOpt.exists(a => (a.balance == 0 && userOpt.exists(_.userId == authenticatedUser.userId)) || authenticatedUserAttributes.exists(_.name == \"role\" && _.value == \"manager\"))", - description = "Allow account closure if zero balance self-service or manager override" - ), - AbacRuleExampleJsonV600( - category = "Business Logic - VIP Processing", - title = "VIP Priority Check", - code = "(customerAttributes.exists(_.name == \"vip_status\" && _.value == \"true\") || accountAttributes.exists(_.name == \"account_tier\" && _.value == \"platinum\"))", - description = "Check if customer or account qualifies for VIP priority processing" - ), - AbacRuleExampleJsonV600( - category = "Business Logic - Joint Account", - title = "Joint Account Access", - code = "accountOpt.exists(a => a.accountHolders.exists(h => h.userId == authenticatedUser.userId || h.emailAddress == authenticatedUser.emailAddress))", - description = "Check if authenticated user is one of the account holders" + category = "Access Control - Risk-Based Transaction Review", + title = "Fraud Analyst High-Risk Transaction Access", + code = "authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"fraud_analyst\") && callContext.exists(c => c.verb.exists(_ == \"GET\") && c.implementedByPartialFunction.exists(_.contains(\"Transaction\"))) && transactionAttributes.exists(ta => ta.name == \"risk_score\" && ta.value.toInt >= 75) && transactionOpt.exists(_.status.exists(_ != \"COMPLETED\"))", + description = "Allow fraud analysts to GET high-risk (score ≥75) non-completed transactions" ) ), available_operators = List( From 63b46b77f2a11ed2e52d30bf801eee68fa40d521 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Tue, 13 Jan 2026 14:33:26 +0100 Subject: [PATCH 37/48] Docfix: Fewer ABA examples part 2 --- .../scala/code/api/v6_0_0/APIMethods600.scala | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 40ab1fc7d..42ce7e368 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -5247,23 +5247,11 @@ trait APIMethods600 { code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"10.\"))) && authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"compliance_officer\") && transactionOpt.exists(_.amount > 10000)", description = "Allow compliance officers on internal network to review high-value transactions over 10,000" ), - AbacRuleExampleJsonV600( - category = "Access Control - Customer Data", - title = "Regional Manager Customer Access via Mobile", - code = "authenticatedUserAttributes.exists(a => a.name == \"region\" && customerAttributes.exists(ca => ca.name == \"region\" && a.value == ca.value)) && callContext.exists(_.userAgent.exists(_.contains(\"Mobile\"))) && customerOpt.exists(_.relationshipStatus == \"ACTIVE\")", - description = "Allow regional managers to access active customers in their region when using mobile app" - ), - AbacRuleExampleJsonV600( - category = "Access Control - Transaction Modification", - title = "Authorized Delegation Transaction Update", - code = "onBehalfOfUserOpt.exists(_.userId != authenticatedUser.userId) && onBehalfOfUserAttributes.exists(a => a.name == \"delegation_level\" && a.value == \"full\") && callContext.exists(_.verb.exists(_ == \"PUT\")) && transactionOpt.exists(t => t.amount < 5000)", - description = "Allow full delegation to update transactions under 5000 via PUT requests" - ), AbacRuleExampleJsonV600( category = "Access Control - Account Balance", - title = "Department Head Same-Department Account Read", - code = "authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"department_head\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance > 0)", - description = "Allow department heads to read account details for accounts in their department with positive balance" + title = "Department Head Same-Department Account Read where overdrawn", + code = "authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"department_head\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance < 0)", + description = "Allow department heads to read account details for overdrawn accounts in their department" ), AbacRuleExampleJsonV600( category = "Access Control - Transaction Request Approval", From 9576a5ccc780f6aa0c3c272acef3ced469839d9e Mon Sep 17 00:00:00 2001 From: simonredfern Date: Tue, 13 Jan 2026 16:38:08 +0100 Subject: [PATCH 38/48] Feature: ABAC has entitlements for auth user and obo user --- .../scala/code/abacrule/AbacRuleEngine.scala | 27 ++++++++++--- .../scala/code/api/v6_0_0/APIMethods600.scala | 40 +++++++++++-------- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala b/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala index 5b531af98..8b8dc2cad 100644 --- a/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala +++ b/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala @@ -4,6 +4,7 @@ import code.api.util.{APIUtil, CallContext, DynamicUtil} import code.bankconnectors.Connector import code.model.dataAccess.ResourceUser import code.users.Users +import code.entitlement.Entitlement import com.openbankproject.commons.model._ import com.openbankproject.commons.ExecutionContext.Implicits.global import net.liftweb.common.{Box, Empty, Failure, Full} @@ -26,12 +27,12 @@ object AbacRuleEngine { /** * Type alias for compiled ABAC rule function - * Parameters: authenticatedUser (logged in), authenticatedUserAttributes (non-personal), authenticatedUserAuthContext (auth context), - * onBehalfOfUser (delegation), onBehalfOfUserAttributes, onBehalfOfUserAuthContext, + * Parameters: authenticatedUser (logged in), authenticatedUserAttributes (non-personal), authenticatedUserAuthContext (auth context), authenticatedUserEntitlements (roles), + * onBehalfOfUser (delegation), onBehalfOfUserAttributes, onBehalfOfUserAuthContext, onBehalfOfUserEntitlements, * user, userAttributes, bankOpt, bankAttributes, accountOpt, accountAttributes, transactionOpt, transactionAttributes, customerOpt, customerAttributes * Returns: Boolean (true = allow access, false = deny access) */ - type AbacRuleFunction = (User, List[UserAttributeTrait], List[UserAuthContext], Option[User], List[UserAttributeTrait], List[UserAuthContext], Option[User], List[UserAttributeTrait], Option[Bank], List[BankAttributeTrait], Option[BankAccount], List[AccountAttribute], Option[Transaction], List[TransactionAttribute], Option[TransactionRequest], List[TransactionRequestAttributeTrait], Option[Customer], List[CustomerAttribute], Option[CallContext]) => Boolean + type AbacRuleFunction = (User, List[UserAttributeTrait], List[UserAuthContext], List[Entitlement], Option[User], List[UserAttributeTrait], List[UserAuthContext], List[Entitlement], Option[User], List[UserAttributeTrait], Option[Bank], List[BankAttributeTrait], Option[BankAccount], List[AccountAttribute], Option[Transaction], List[TransactionAttribute], Option[TransactionRequest], List[TransactionRequestAttributeTrait], Option[Customer], List[CustomerAttribute], Option[CallContext]) => Boolean /** * Compile an ABAC rule from Scala code @@ -75,7 +76,7 @@ object AbacRuleEngine { |import net.liftweb.common._ | |// ABAC Rule Function - |(authenticatedUser: User, authenticatedUserAttributes: List[UserAttributeTrait], authenticatedUserAuthContext: List[UserAuthContext], onBehalfOfUserOpt: Option[User], onBehalfOfUserAttributes: List[UserAttributeTrait], onBehalfOfUserAuthContext: List[UserAuthContext], userOpt: Option[User], userAttributes: List[UserAttributeTrait], bankOpt: Option[Bank], bankAttributes: List[BankAttributeTrait], accountOpt: Option[BankAccount], accountAttributes: List[AccountAttribute], transactionOpt: Option[Transaction], transactionAttributes: List[TransactionAttribute], transactionRequestOpt: Option[TransactionRequest], transactionRequestAttributes: List[TransactionRequestAttributeTrait], customerOpt: Option[Customer], customerAttributes: List[CustomerAttribute], callContext: Option[code.api.util.CallContext]) => { + |(authenticatedUser: User, authenticatedUserAttributes: List[UserAttributeTrait], authenticatedUserAuthContext: List[UserAuthContext], authenticatedUserEntitlements: List[Entitlement], onBehalfOfUserOpt: Option[User], onBehalfOfUserAttributes: List[UserAttributeTrait], onBehalfOfUserAuthContext: List[UserAuthContext], onBehalfOfUserEntitlements: List[Entitlement], userOpt: Option[User], userAttributes: List[UserAttributeTrait], bankOpt: Option[Bank], bankAttributes: List[BankAttributeTrait], accountOpt: Option[BankAccount], accountAttributes: List[AccountAttribute], transactionOpt: Option[Transaction], transactionAttributes: List[TransactionAttribute], transactionRequestOpt: Option[TransactionRequest], transactionRequestAttributes: List[TransactionRequestAttributeTrait], customerOpt: Option[Customer], customerAttributes: List[CustomerAttribute], callContext: Option[code.api.util.CallContext]) => { | $ruleCode |} |""".stripMargin @@ -129,6 +130,12 @@ object AbacRuleEngine { 5.seconds ) + // Fetch entitlements for authenticated user + authenticatedUserEntitlements = Await.result( + code.api.util.NewStyle.function.getEntitlementsByUserId(authenticatedUserId, Some(callContext)), + 5.seconds + ) + // Fetch onBehalfOf user if provided (delegation scenario) onBehalfOfUserOpt <- onBehalfOfUserId match { case Some(obUserId) => Users.users.vend.getUserByUserId(obUserId).map(Some(_)) @@ -155,6 +162,16 @@ object AbacRuleEngine { case None => List.empty[UserAuthContext] } + // Fetch entitlements for onBehalfOf user if provided + onBehalfOfUserEntitlements = onBehalfOfUserId match { + case Some(obUserId) => + Await.result( + code.api.util.NewStyle.function.getEntitlementsByUserId(obUserId, Some(callContext)), + 5.seconds + ) + case None => List.empty[Entitlement] + } + // Fetch target user if userId is provided userOpt <- userId match { case Some(uId) => Users.users.vend.getUserByUserId(uId).map(Some(_)) @@ -274,7 +291,7 @@ object AbacRuleEngine { // Compile and execute the rule compiledFunc <- compileRule(ruleId, rule.ruleCode) result <- tryo { - compiledFunc(authenticatedUser, authenticatedUserAttributes, authenticatedUserAuthContext, onBehalfOfUserOpt, onBehalfOfUserAttributes, onBehalfOfUserAuthContext, userOpt, userAttributes, bankOpt, bankAttributes, accountOpt, accountAttributes, transactionOpt, transactionAttributes, transactionRequestOpt, transactionRequestAttributes, customerOpt, customerAttributes, Some(callContext)) + compiledFunc(authenticatedUser, authenticatedUserAttributes, authenticatedUserAuthContext, authenticatedUserEntitlements, onBehalfOfUserOpt, onBehalfOfUserAttributes, onBehalfOfUserAuthContext, onBehalfOfUserEntitlements, userOpt, userAttributes, bankOpt, bankAttributes, accountOpt, accountAttributes, transactionOpt, transactionAttributes, transactionRequestOpt, transactionRequestAttributes, customerOpt, customerAttributes, Some(callContext)) } } yield result } diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 42ce7e368..c7dbfadfd 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -5116,9 +5116,11 @@ trait APIMethods600 { AbacParameterJsonV600("authenticatedUser", "User", "The logged-in user (always present)", required = true, "User"), AbacParameterJsonV600("authenticatedUserAttributes", "List[UserAttributeTrait]", "Non-personal attributes of authenticated user", required = true, "User"), AbacParameterJsonV600("authenticatedUserAuthContext", "List[UserAuthContext]", "Auth context of authenticated user", required = true, "User"), + AbacParameterJsonV600("authenticatedUserEntitlements", "List[Entitlement]", "Entitlements (roles) of authenticated user", required = true, "User"), AbacParameterJsonV600("onBehalfOfUserOpt", "Option[User]", "User being acted on behalf of (delegation)", required = false, "User"), AbacParameterJsonV600("onBehalfOfUserAttributes", "List[UserAttributeTrait]", "Attributes of delegation user", required = false, "User"), AbacParameterJsonV600("onBehalfOfUserAuthContext", "List[UserAuthContext]", "Auth context of delegation user", required = false, "User"), + AbacParameterJsonV600("onBehalfOfUserEntitlements", "List[Entitlement]", "Entitlements (roles) of delegation user", required = false, "User"), AbacParameterJsonV600("userOpt", "Option[User]", "Target user being evaluated", required = false, "User"), AbacParameterJsonV600("userAttributes", "List[UserAttributeTrait]", "Attributes of target user", required = false, "User"), AbacParameterJsonV600("bankOpt", "Option[Bank]", "Bank context", required = false, "Bank"), @@ -5223,6 +5225,12 @@ trait APIMethods600 { AbacObjectPropertyJsonV600("value", "String", "Attribute value"), AbacObjectPropertyJsonV600("attributeType", "AttributeType", "Attribute type") )), + AbacObjectTypeJsonV600("Entitlement", "User entitlement (role)", List( + AbacObjectPropertyJsonV600("entitlementId", "String", "Entitlement ID"), + AbacObjectPropertyJsonV600("roleName", "String", "Role name (e.g., CanCreateAccount, CanReadTransactions)"), + AbacObjectPropertyJsonV600("bankId", "String", "Bank ID (empty string for system-wide roles)"), + AbacObjectPropertyJsonV600("userId", "String", "User ID this entitlement belongs to") + )), AbacObjectTypeJsonV600("CallContext", "Request context with metadata", List( AbacObjectPropertyJsonV600("correlationId", "String", "Correlation ID for request tracking"), AbacObjectPropertyJsonV600("url", "Option[String]", "Request URL"), @@ -5238,50 +5246,50 @@ trait APIMethods600 { AbacRuleExampleJsonV600( category = "Access Control - Account Access", title = "Branch Manager Internal Account Access", - code = "authenticatedUserAttributes.exists(a => a.name == \"branch\" && accountAttributes.exists(aa => aa.name == \"branch\" && a.value == aa.value)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(_.accountType == \"CURRENT\")", - description = "Allow GET access to current accounts only when user's branch matches account's branch" + code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"branch\" && accountAttributes.exists(aa => aa.name == \"branch\" && a.value == aa.value)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(_.accountType == \"CURRENT\")", + description = "Allow GET access to current accounts when user has CanReadAccountsAtOneBank role and branch matches account's branch" ), AbacRuleExampleJsonV600( category = "Access Control - Transaction Access", title = "Internal Network High-Value Transaction Review", - code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"10.\"))) && authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"compliance_officer\") && transactionOpt.exists(_.amount > 10000)", - description = "Allow compliance officers on internal network to review high-value transactions over 10,000" + code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"10.\"))) && authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && transactionOpt.exists(_.amount > 10000)", + description = "Allow users with CanReadTransactionsAtOneBank role on internal network to review high-value transactions over 10,000" ), AbacRuleExampleJsonV600( category = "Access Control - Account Balance", title = "Department Head Same-Department Account Read where overdrawn", - code = "authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"department_head\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance < 0)", - description = "Allow department heads to read account details for overdrawn accounts in their department" + code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance < 0)", + description = "Allow users with CanReadAccountsAtOneBank role to read overdrawn accounts in their department" ), AbacRuleExampleJsonV600( category = "Access Control - Transaction Request Approval", title = "Manager Internal Network Transaction Approval", - code = "authenticatedUserAttributes.exists(a => a.name == \"role\" && List(\"manager\", \"supervisor\").contains(a.value)) && callContext.exists(_.ipAddress.exists(ip => ip.startsWith(\"10.\") || ip.startsWith(\"192.168.\"))) && transactionRequestOpt.exists(tr => tr.status == \"PENDING\" && tr.charge.value.toDouble < 50000)", - description = "Allow managers/supervisors on internal network to approve pending transaction requests under 50,000" + code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateTransactionRequest\") && callContext.exists(_.ipAddress.exists(ip => ip.startsWith(\"10.\") || ip.startsWith(\"192.168.\"))) && transactionRequestOpt.exists(tr => tr.status == \"PENDING\" && tr.charge.value.toDouble < 50000)", + description = "Allow users with CanCreateTransactionRequest role on internal network to approve pending transaction requests under 50,000" ), AbacRuleExampleJsonV600( category = "Access Control - Customer Onboarding", title = "KYC Officer Customer Creation from Branch", - code = "authenticatedUserAttributes.exists(a => a.name == \"certification\" && a.value == \"kyc_certified\") && callContext.exists(_.verb.exists(_ == \"POST\")) && callContext.exists(_.ipAddress.exists(_.startsWith(\"10.20.\"))) && customerAttributes.exists(ca => ca.name == \"onboarding_status\" && ca.value == \"pending\")", - description = "Allow KYC certified officers to create customers via POST from branch network (10.20.x.x) when status is pending" + code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateCustomer\") && authenticatedUserAttributes.exists(a => a.name == \"certification\" && a.value == \"kyc_certified\") && callContext.exists(_.verb.exists(_ == \"POST\")) && callContext.exists(_.ipAddress.exists(_.startsWith(\"10.20.\"))) && customerAttributes.exists(ca => ca.name == \"onboarding_status\" && ca.value == \"pending\")", + description = "Allow users with CanCreateCustomer role and KYC certification to create customers via POST from branch network (10.20.x.x) when status is pending" ), AbacRuleExampleJsonV600( category = "Access Control - Cross-Border Transaction", title = "International Team Foreign Currency Transaction", - code = "authenticatedUserAttributes.exists(a => a.name == \"team\" && a.value == \"international\") && callContext.exists(_.url.exists(_.contains(\"/transactions/\"))) && transactionOpt.exists(t => t.currency != \"USD\" && t.amount < 100000) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"international_enabled\" && aa.value == \"true\"))", - description = "Allow international team to access foreign currency transactions under 100k on international-enabled accounts" + code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"team\" && a.value == \"international\") && callContext.exists(_.url.exists(_.contains(\"/transactions/\"))) && transactionOpt.exists(t => t.currency != \"USD\" && t.amount < 100000) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"international_enabled\" && aa.value == \"true\"))", + description = "Allow international team users with CanReadTransactionsAtOneBank role to access foreign currency transactions under 100k on international-enabled accounts" ), AbacRuleExampleJsonV600( category = "Access Control - Delegated Account Management", title = "Assistant with Limited Delegation Account View", - code = "onBehalfOfUserOpt.isDefined && onBehalfOfUserAttributes.exists(a => a.name == \"role\" && a.value == \"executive\") && authenticatedUserAttributes.exists(a => a.name == \"assistant_of\" && onBehalfOfUserOpt.exists(u => a.value == u.userId)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"tier\" && List(\"gold\", \"platinum\").contains(aa.value)))", - description = "Allow assistants to view gold/platinum accounts via GET when acting on behalf of their assigned executive" + code = "onBehalfOfUserOpt.isDefined && onBehalfOfUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"assistant_of\" && onBehalfOfUserOpt.exists(u => a.value == u.userId)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"tier\" && List(\"gold\", \"platinum\").contains(aa.value)))", + description = "Allow assistants to view gold/platinum accounts via GET when acting on behalf of a user with CanReadAccountsAtOneBank role" ), AbacRuleExampleJsonV600( category = "Access Control - Risk-Based Transaction Review", title = "Fraud Analyst High-Risk Transaction Access", - code = "authenticatedUserAttributes.exists(a => a.name == \"role\" && a.value == \"fraud_analyst\") && callContext.exists(c => c.verb.exists(_ == \"GET\") && c.implementedByPartialFunction.exists(_.contains(\"Transaction\"))) && transactionAttributes.exists(ta => ta.name == \"risk_score\" && ta.value.toInt >= 75) && transactionOpt.exists(_.status.exists(_ != \"COMPLETED\"))", - description = "Allow fraud analysts to GET high-risk (score ≥75) non-completed transactions" + code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && callContext.exists(c => c.verb.exists(_ == \"GET\") && c.implementedByPartialFunction.exists(_.contains(\"Transaction\"))) && transactionAttributes.exists(ta => ta.name == \"risk_score\" && ta.value.toInt >= 75) && transactionOpt.exists(_.status.exists(_ != \"COMPLETED\"))", + description = "Allow users with CanReadTransactionsAtOneBank role to GET high-risk (score ≥75) non-completed transactions" ) ), available_operators = List( From d95189e36fa1249939cedc26ea7bbb3f5041859b Mon Sep 17 00:00:00 2001 From: simonredfern Date: Tue, 13 Jan 2026 19:07:23 +0100 Subject: [PATCH 39/48] Aligning ABAC examples with actual field names --- .../scala/code/api/v6_0_0/APIMethods600.scala | 80 +++++++++---------- .../code/api/v6_0_0/JSONFactory6.0.0.scala | 8 +- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index c7dbfadfd..ef4f6337b 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -5076,16 +5076,16 @@ trait APIMethods600 { ), examples = List( AbacRuleExampleJsonV600( - category = "User Access", - title = "Check User Identity", - code = "authenticatedUser.userId == user.userId", - description = "Verify that the authenticated user matches the target user" + rule_name = "Check User Identity", + rule_code = "authenticatedUser.userId == user.userId", + description = "Verify that the authenticated user matches the target user", + is_active = true ), AbacRuleExampleJsonV600( - category = "Bank Access", - title = "Check Specific Bank", - code = "bankOpt.isDefined && bankOpt.get.bankId.value == \"gh.29.uk\"", - description = "Verify that the bank context is defined and matches a specific bank ID" + rule_name = "Check Specific Bank", + rule_code = "bankOpt.isDefined && bankOpt.get.bankId.value == \"gh.29.uk\"", + description = "Verify that the bank context is defined and matches a specific bank ID", + is_active = true ) ), available_operators = List("==", "!=", "&&", "||", "!", ">", "<", ">=", "<=", "contains", "isDefined"), @@ -5244,52 +5244,52 @@ trait APIMethods600 { ), examples = List( AbacRuleExampleJsonV600( - category = "Access Control - Account Access", - title = "Branch Manager Internal Account Access", - code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"branch\" && accountAttributes.exists(aa => aa.name == \"branch\" && a.value == aa.value)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(_.accountType == \"CURRENT\")", - description = "Allow GET access to current accounts when user has CanReadAccountsAtOneBank role and branch matches account's branch" + rule_name = "Branch Manager Internal Account Access", + rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"branch\" && accountAttributes.exists(aa => aa.name == \"branch\" && a.value == aa.value)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(_.accountType == \"CURRENT\")", + description = "Allow GET access to current accounts when user has CanReadAccountsAtOneBank role and branch matches account's branch", + is_active = true ), AbacRuleExampleJsonV600( - category = "Access Control - Transaction Access", - title = "Internal Network High-Value Transaction Review", - code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"10.\"))) && authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && transactionOpt.exists(_.amount > 10000)", - description = "Allow users with CanReadTransactionsAtOneBank role on internal network to review high-value transactions over 10,000" + rule_name = "Internal Network High-Value Transaction Review", + rule_code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"10.\"))) && authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && transactionOpt.exists(_.amount > 10000)", + description = "Allow users with CanReadTransactionsAtOneBank role on internal network to review high-value transactions over 10,000", + is_active = true ), AbacRuleExampleJsonV600( - category = "Access Control - Account Balance", - title = "Department Head Same-Department Account Read where overdrawn", - code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance < 0)", - description = "Allow users with CanReadAccountsAtOneBank role to read overdrawn accounts in their department" + rule_name = "Department Head Same-Department Account Read where overdrawn", + rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance < 0)", + description = "Allow users with CanReadAccountsAtOneBank role to read overdrawn accounts in their department", + is_active = true ), AbacRuleExampleJsonV600( - category = "Access Control - Transaction Request Approval", - title = "Manager Internal Network Transaction Approval", - code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateTransactionRequest\") && callContext.exists(_.ipAddress.exists(ip => ip.startsWith(\"10.\") || ip.startsWith(\"192.168.\"))) && transactionRequestOpt.exists(tr => tr.status == \"PENDING\" && tr.charge.value.toDouble < 50000)", - description = "Allow users with CanCreateTransactionRequest role on internal network to approve pending transaction requests under 50,000" + rule_name = "Manager Internal Network Transaction Approval", + rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateTransactionRequest\") && callContext.exists(_.ipAddress.exists(ip => ip.startsWith(\"10.\") || ip.startsWith(\"192.168.\"))) && transactionRequestOpt.exists(tr => tr.status == \"PENDING\" && tr.charge.value.toDouble < 50000)", + description = "Allow users with CanCreateTransactionRequest role on internal network to approve pending transaction requests under 50,000", + is_active = true ), AbacRuleExampleJsonV600( - category = "Access Control - Customer Onboarding", - title = "KYC Officer Customer Creation from Branch", - code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateCustomer\") && authenticatedUserAttributes.exists(a => a.name == \"certification\" && a.value == \"kyc_certified\") && callContext.exists(_.verb.exists(_ == \"POST\")) && callContext.exists(_.ipAddress.exists(_.startsWith(\"10.20.\"))) && customerAttributes.exists(ca => ca.name == \"onboarding_status\" && ca.value == \"pending\")", - description = "Allow users with CanCreateCustomer role and KYC certification to create customers via POST from branch network (10.20.x.x) when status is pending" + rule_name = "KYC Officer Customer Creation from Branch", + rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateCustomer\") && authenticatedUserAttributes.exists(a => a.name == \"certification\" && a.value == \"kyc_certified\") && callContext.exists(_.verb.exists(_ == \"POST\")) && callContext.exists(_.ipAddress.exists(_.startsWith(\"10.20.\"))) && customerAttributes.exists(ca => ca.name == \"onboarding_status\" && ca.value == \"pending\")", + description = "Allow users with CanCreateCustomer role and KYC certification to create customers via POST from branch network (10.20.x.x) when status is pending", + is_active = true ), AbacRuleExampleJsonV600( - category = "Access Control - Cross-Border Transaction", - title = "International Team Foreign Currency Transaction", - code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"team\" && a.value == \"international\") && callContext.exists(_.url.exists(_.contains(\"/transactions/\"))) && transactionOpt.exists(t => t.currency != \"USD\" && t.amount < 100000) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"international_enabled\" && aa.value == \"true\"))", - description = "Allow international team users with CanReadTransactionsAtOneBank role to access foreign currency transactions under 100k on international-enabled accounts" + rule_name = "International Team Foreign Currency Transaction", + rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"team\" && a.value == \"international\") && callContext.exists(_.url.exists(_.contains(\"/transactions/\"))) && transactionOpt.exists(t => t.currency != \"USD\" && t.amount < 100000) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"international_enabled\" && aa.value == \"true\"))", + description = "Allow international team users with CanReadTransactionsAtOneBank role to access foreign currency transactions under 100k on international-enabled accounts", + is_active = true ), AbacRuleExampleJsonV600( - category = "Access Control - Delegated Account Management", - title = "Assistant with Limited Delegation Account View", - code = "onBehalfOfUserOpt.isDefined && onBehalfOfUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"assistant_of\" && onBehalfOfUserOpt.exists(u => a.value == u.userId)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"tier\" && List(\"gold\", \"platinum\").contains(aa.value)))", - description = "Allow assistants to view gold/platinum accounts via GET when acting on behalf of a user with CanReadAccountsAtOneBank role" + rule_name = "Assistant with Limited Delegation Account View", + rule_code = "onBehalfOfUserOpt.isDefined && onBehalfOfUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"assistant_of\" && onBehalfOfUserOpt.exists(u => a.value == u.userId)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"tier\" && List(\"gold\", \"platinum\").contains(aa.value)))", + description = "Allow assistants to view gold/platinum accounts via GET when acting on behalf of a user with CanReadAccountsAtOneBank role", + is_active = true ), AbacRuleExampleJsonV600( - category = "Access Control - Risk-Based Transaction Review", - title = "Fraud Analyst High-Risk Transaction Access", - code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && callContext.exists(c => c.verb.exists(_ == \"GET\") && c.implementedByPartialFunction.exists(_.contains(\"Transaction\"))) && transactionAttributes.exists(ta => ta.name == \"risk_score\" && ta.value.toInt >= 75) && transactionOpt.exists(_.status.exists(_ != \"COMPLETED\"))", - description = "Allow users with CanReadTransactionsAtOneBank role to GET high-risk (score ≥75) non-completed transactions" + rule_name = "Fraud Analyst High-Risk Transaction Access", + rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && callContext.exists(c => c.verb.exists(_ == \"GET\") && c.implementedByPartialFunction.exists(_.contains(\"Transaction\"))) && transactionAttributes.exists(ta => ta.name == \"risk_score\" && ta.value.toInt >= 75) && transactionOpt.exists(_.status.exists(_ != \"COMPLETED\"))", + description = "Allow users with CanReadTransactionsAtOneBank role to GET high-risk (score ≥75) non-completed transactions", + is_active = true ) ), available_operators = List( diff --git a/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala b/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala index 36ab2d96b..7e64eec36 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala @@ -459,10 +459,10 @@ case class AbacObjectTypeJsonV600( ) case class AbacRuleExampleJsonV600( - category: String, - title: String, - code: String, - description: String + rule_name: String, + rule_code: String, + description: String, + is_active: Boolean ) case class AbacRuleSchemaJsonV600( From f95e8b8645d9bd52261cb14a799cc3ba59e21288 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Wed, 14 Jan 2026 09:32:23 +0100 Subject: [PATCH 40/48] ABAC Policy instead of tag --- .../scala/code/abacrule/AbacRuleEngine.scala | 64 ++++++++ .../scala/code/abacrule/AbacRuleTrait.scala | 23 +++ .../scala/code/api/constant/constant.scala | 13 ++ .../scala/code/api/v6_0_0/APIMethods600.scala | 142 +++++++++++++++++- .../code/api/v6_0_0/JSONFactory6.0.0.scala | 14 ++ 5 files changed, 255 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala b/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala index 8b8dc2cad..2145c7831 100644 --- a/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala +++ b/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala @@ -298,6 +298,70 @@ object AbacRuleEngine { + /** + * Execute all active ABAC rules with a specific policy (OR logic - at least one must pass) + * @param logic The logic to apply: "AND" (all must pass), "OR" (any must pass), "XOR" (exactly one must pass) + * + * @param policy The policy to filter rules by + * @param authenticatedUserId The ID of the authenticated user + * @param onBehalfOfUserId Optional ID of user being acted on behalf of + * @param userId The ID of the target user to evaluate + * @param callContext Call context for fetching objects + * @param bankId Optional bank ID + * @param accountId Optional account ID + * @param viewId Optional view ID + * @param transactionId Optional transaction ID + * @param transactionRequestId Optional transaction request ID + * @param customerId Optional customer ID + * @return Box[Boolean] - Full(true) if at least one rule passes (OR logic), Full(false) if all fail + */ + def executeRulesByPolicy( + policy: String, + authenticatedUserId: String, + onBehalfOfUserId: Option[String] = None, + userId: Option[String] = None, + callContext: CallContext, + bankId: Option[String] = None, + accountId: Option[String] = None, + viewId: Option[String] = None, + transactionId: Option[String] = None, + transactionRequestId: Option[String] = None, + customerId: Option[String] = None + ): Box[Boolean] = { + val rules = MappedAbacRuleProvider.getActiveAbacRulesByPolicy(policy) + + if (rules.isEmpty) { + // No rules for this policy - default to allow + Full(true) + } else { + // Execute all rules and check if at least one passes + val results = rules.map { rule => + executeRule( + ruleId = rule.abacRuleId, + authenticatedUserId = authenticatedUserId, + onBehalfOfUserId = onBehalfOfUserId, + userId = userId, + callContext = callContext, + bankId = bankId, + accountId = accountId, + viewId = viewId, + transactionId = transactionId, + transactionRequestId = transactionRequestId, + customerId = customerId + ) + } + + // Count successes and failures + val successes = results.filter { + case Full(true) => true + case _ => false + } + + // At least one rule must pass (OR logic) + Full(successes.nonEmpty) + } + } + /** * Validate ABAC rule code by attempting to compile it * diff --git a/obp-api/src/main/scala/code/abacrule/AbacRuleTrait.scala b/obp-api/src/main/scala/code/abacrule/AbacRuleTrait.scala index e4309f342..9e9a22885 100644 --- a/obp-api/src/main/scala/code/abacrule/AbacRuleTrait.scala +++ b/obp-api/src/main/scala/code/abacrule/AbacRuleTrait.scala @@ -14,6 +14,7 @@ trait AbacRuleTrait { def ruleCode: String def isActive: Boolean def description: String + def policy: String def createdByUserId: String def updatedByUserId: String } @@ -30,6 +31,7 @@ class AbacRule extends AbacRuleTrait with LongKeyedMapper[AbacRule] with IdPK wi override def defaultValue = true } object Description extends MappedText(this) + object Policy extends MappedText(this) object CreatedByUserId extends MappedString(this, 255) object UpdatedByUserId extends MappedString(this, 255) @@ -38,6 +40,7 @@ class AbacRule extends AbacRuleTrait with LongKeyedMapper[AbacRule] with IdPK wi override def ruleCode: String = RuleCode.get override def isActive: Boolean = IsActive.get override def description: String = Description.get + override def policy: String = Policy.get override def createdByUserId: String = CreatedByUserId.get override def updatedByUserId: String = UpdatedByUserId.get } @@ -51,10 +54,13 @@ trait AbacRuleProvider { def getAbacRuleByName(ruleName: String): Box[AbacRuleTrait] def getAllAbacRules(): List[AbacRuleTrait] def getActiveAbacRules(): List[AbacRuleTrait] + def getAbacRulesByPolicy(policy: String): List[AbacRuleTrait] + def getActiveAbacRulesByPolicy(policy: String): List[AbacRuleTrait] def createAbacRule( ruleName: String, ruleCode: String, description: String, + policy: String, isActive: Boolean, createdBy: String ): Box[AbacRuleTrait] @@ -63,6 +69,7 @@ trait AbacRuleProvider { ruleName: String, ruleCode: String, description: String, + policy: String, isActive: Boolean, updatedBy: String ): Box[AbacRuleTrait] @@ -87,10 +94,23 @@ object MappedAbacRuleProvider extends AbacRuleProvider { AbacRule.findAll(By(AbacRule.IsActive, true)) } + override def getAbacRulesByPolicy(policy: String): List[AbacRuleTrait] = { + AbacRule.findAll().filter { rule => + rule.policy.split(",").map(_.trim).contains(policy) + } + } + + override def getActiveAbacRulesByPolicy(policy: String): List[AbacRuleTrait] = { + AbacRule.findAll(By(AbacRule.IsActive, true)).filter { rule => + rule.policy.split(",").map(_.trim).contains(policy) + } + } + override def createAbacRule( ruleName: String, ruleCode: String, description: String, + policy: String, isActive: Boolean, createdBy: String ): Box[AbacRuleTrait] = { @@ -99,6 +119,7 @@ object MappedAbacRuleProvider extends AbacRuleProvider { .RuleName(ruleName) .RuleCode(ruleCode) .Description(description) + .Policy(policy) .IsActive(isActive) .CreatedByUserId(createdBy) .UpdatedByUserId(createdBy) @@ -111,6 +132,7 @@ object MappedAbacRuleProvider extends AbacRuleProvider { ruleName: String, ruleCode: String, description: String, + policy: String, isActive: Boolean, updatedBy: String ): Box[AbacRuleTrait] = { @@ -121,6 +143,7 @@ object MappedAbacRuleProvider extends AbacRuleProvider { .RuleName(ruleName) .RuleCode(ruleCode) .Description(description) + .Policy(policy) .IsActive(isActive) .UpdatedByUserId(updatedBy) .saveMe() diff --git a/obp-api/src/main/scala/code/api/constant/constant.scala b/obp-api/src/main/scala/code/api/constant/constant.scala index 73cee00a6..9816ad4a2 100644 --- a/obp-api/src/main/scala/code/api/constant/constant.scala +++ b/obp-api/src/main/scala/code/api/constant/constant.scala @@ -266,6 +266,19 @@ object Constant extends MdcLoggable { // ABAC Cache Prefixes (with global namespace and versioning) def ABAC_RULE_PREFIX: String = getVersionedCachePrefix(ABAC_RULE_NAMESPACE) + // ABAC Policy Constants + final val ABAC_POLICY_ACCOUNT_ACCESS = "account-access" + + // List of all ABAC Policies + final val ABAC_POLICIES: List[String] = List( + ABAC_POLICY_ACCOUNT_ACCESS + ) + + // Map of ABAC Policies to their descriptions + final val ABAC_POLICY_DESCRIPTIONS: Map[String, String] = Map( + ABAC_POLICY_ACCOUNT_ACCESS -> "Rules for controlling access to account information and account-related operations" + ) + final val CAN_SEE_TRANSACTION_OTHER_BANK_ACCOUNT = "can_see_transaction_other_bank_account" final val CAN_SEE_TRANSACTION_METADATA = "can_see_transaction_metadata" final val CAN_SEE_TRANSACTION_DESCRIPTION = "can_see_transaction_description" diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index ef4f6337b..677811329 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -27,7 +27,7 @@ import code.api.v5_0_0.{ViewJsonV500, ViewsJsonV500} import code.api.v5_1_0.{JSONFactory510, PostCustomerLegalNameJsonV510} import code.api.dynamic.entity.helper.{DynamicEntityHelper, DynamicEntityInfo} import code.api.v6_0_0.JSONFactory600.{AddUserToGroupResponseJsonV600, DynamicEntityDiagnosticsJsonV600, DynamicEntityIssueJsonV600, GroupEntitlementJsonV600, GroupEntitlementsJsonV600, GroupJsonV600, GroupsJsonV600, PostGroupJsonV600, PostGroupMembershipJsonV600, PostResetPasswordUrlJsonV600, PutGroupJsonV600, ReferenceTypeJsonV600, ReferenceTypesJsonV600, ResetPasswordUrlJsonV600, RoleWithEntitlementCountJsonV600, RolesWithEntitlementCountsJsonV600, ScannedApiVersionJsonV600, UpdateViewJsonV600, UserGroupMembershipJsonV600, UserGroupMembershipsJsonV600, ValidateUserEmailJsonV600, ValidateUserEmailResponseJsonV600, ViewJsonV600, ViewPermissionJsonV600, ViewPermissionsJsonV600, ViewsJsonV600, createAbacRuleJsonV600, createAbacRulesJsonV600, createActiveRateLimitsJsonV600, createCallLimitJsonV600, createRedisCallCountersJson} -import code.api.v6_0_0.{AbacRuleJsonV600, AbacRuleResultJsonV600, AbacRulesJsonV600, CacheConfigJsonV600, CacheInfoJsonV600, CacheNamespaceInfoJsonV600, CreateAbacRuleJsonV600, CurrentConsumerJsonV600, ExecuteAbacRuleJsonV600, InMemoryCacheStatusJsonV600, RedisCacheStatusJsonV600, UpdateAbacRuleJsonV600} +import code.api.v6_0_0.{AbacRuleJsonV600, AbacRuleResultJsonV600, AbacRulesJsonV600, CacheConfigJsonV600, CacheInfoJsonV600, CacheNamespaceInfoJsonV600, CreateAbacRuleJsonV600, CurrentConsumerJsonV600, ExecuteAbacRuleJsonV600, InMemoryCacheStatusJsonV600, RedisCacheStatusJsonV600, UpdateAbacRuleJsonV600, AbacPoliciesJsonV600, AbacPolicyJsonV600} import code.api.v6_0_0.OBPAPI6_0_0 import code.abacrule.{AbacRuleEngine, MappedAbacRuleProvider} import code.metrics.APIMetrics @@ -4732,6 +4732,7 @@ trait APIMethods600 { rule_name = "admin_only", rule_code = """user.emailAddress.contains("admin")""", description = "Only allow access to users with admin email", + policy = "user-access,admin", is_active = true ), AbacRuleJsonV600( @@ -4740,6 +4741,7 @@ trait APIMethods600 { rule_code = """user.emailAddress.contains("admin")""", is_active = true, description = "Only allow access to users with admin email", + policy = "user-access,admin", created_by_user_id = "user123", updated_by_user_id = "user123" ), @@ -4779,6 +4781,7 @@ trait APIMethods600 { ruleName = createJson.rule_name, ruleCode = createJson.rule_code, description = createJson.description, + policy = createJson.policy, isActive = createJson.is_active, createdBy = user.userId ) @@ -4815,6 +4818,7 @@ trait APIMethods600 { rule_code = """user.emailAddress.contains("admin")""", is_active = true, description = "Only allow access to users with admin email", + policy = "user-access,admin", created_by_user_id = "user123", updated_by_user_id = "user123" ), @@ -4870,6 +4874,7 @@ trait APIMethods600 { rule_code = """user.emailAddress.contains("admin")""", is_active = true, description = "Only allow access to users with admin email", + policy = "user-access,admin", created_by_user_id = "user123", updated_by_user_id = "user123" ) @@ -4899,6 +4904,75 @@ trait APIMethods600 { } } + staticResourceDocs += ResourceDoc( + getAbacRulesByPolicy, + implementedInApiVersion, + nameOf(getAbacRulesByPolicy), + "GET", + "/management/abac-rules/policy/POLICY", + "Get ABAC Rules by Policy", + s"""Get all ABAC rules that belong to a specific policy. + | + |Multiple rules can share the same policy. Rules with multiple policies (comma-separated) + |will be returned if any of their policies match the requested policy. + | + |**Documentation:** + |- ${Glossary.getGlossaryItemLink("ABAC_Simple_Guide")} - Getting started with ABAC rules + |- ${Glossary.getGlossaryItemLink("ABAC_Parameters_Summary")} - Complete list of all 18 parameters + |- ${Glossary.getGlossaryItemLink("ABAC_Object_Properties_Reference")} - Detailed property reference + | + |${userAuthenticationMessage(true)} + | + |""".stripMargin, + EmptyBody, + AbacRulesJsonV600( + abac_rules = List( + AbacRuleJsonV600( + abac_rule_id = "abc123", + rule_name = "admin_only", + rule_code = """user.emailAddress.contains("admin")""", + is_active = true, + description = "Only allow access to users with admin email", + policy = "user-access,admin", + created_by_user_id = "user123", + updated_by_user_id = "user123" + ), + AbacRuleJsonV600( + abac_rule_id = "def456", + rule_name = "admin_department_check", + rule_code = """user.department == "admin"""", + is_active = true, + description = "Check if user is in admin department", + policy = "admin", + created_by_user_id = "user123", + updated_by_user_id = "user123" + ) + ) + ), + List( + UserNotLoggedIn, + UserHasMissingRoles, + UnknownError + ), + List(apiTagABAC), + Some(List(canGetAbacRule)) + ) + + lazy val getAbacRulesByPolicy: OBPEndpoint = { + case "management" :: "abac-rules" :: "policy" :: policy :: Nil JsonGet _ => { + cc => implicit val ec = EndpointContext(Some(cc)) + for { + (Full(user), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement("", user.userId, canGetAbacRule, callContext) + rules <- Future { + MappedAbacRuleProvider.getAbacRulesByPolicy(policy) + } + } yield { + (createAbacRulesJsonV600(rules), HttpCode.`200`(callContext)) + } + } + } + staticResourceDocs += ResourceDoc( updateAbacRule, implementedInApiVersion, @@ -4920,6 +4994,7 @@ trait APIMethods600 { rule_name = "admin_only_updated", rule_code = """user.emailAddress.contains("admin") && user.provider == "obp"""", description = "Only allow access to OBP admin users", + policy = "user-access,admin,obp", is_active = true ), AbacRuleJsonV600( @@ -4928,6 +5003,7 @@ trait APIMethods600 { rule_code = """user.emailAddress.contains("admin") && user.provider == "obp"""", is_active = true, description = "Only allow access to OBP admin users", + policy = "user-access,admin,obp", created_by_user_id = "user123", updated_by_user_id = "user456" ), @@ -4962,6 +5038,7 @@ trait APIMethods600 { ruleName = updateJson.rule_name, ruleCode = updateJson.rule_code, description = updateJson.description, + policy = updateJson.policy, isActive = updateJson.is_active, updatedBy = user.userId ) @@ -5079,11 +5156,13 @@ trait APIMethods600 { rule_name = "Check User Identity", rule_code = "authenticatedUser.userId == user.userId", description = "Verify that the authenticated user matches the target user", + policy = "user-access", is_active = true ), AbacRuleExampleJsonV600( rule_name = "Check Specific Bank", rule_code = "bankOpt.isDefined && bankOpt.get.bankId.value == \"gh.29.uk\"", + policy = "bank-access", description = "Verify that the bank context is defined and matches a specific bank ID", is_active = true ) @@ -5247,48 +5326,56 @@ trait APIMethods600 { rule_name = "Branch Manager Internal Account Access", rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"branch\" && accountAttributes.exists(aa => aa.name == \"branch\" && a.value == aa.value)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(_.accountType == \"CURRENT\")", description = "Allow GET access to current accounts when user has CanReadAccountsAtOneBank role and branch matches account's branch", + policy = "account-access", is_active = true ), AbacRuleExampleJsonV600( rule_name = "Internal Network High-Value Transaction Review", rule_code = "callContext.exists(_.ipAddress.exists(_.startsWith(\"10.\"))) && authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && transactionOpt.exists(_.amount > 10000)", description = "Allow users with CanReadTransactionsAtOneBank role on internal network to review high-value transactions over 10,000", + policy = "transaction-access", is_active = true ), AbacRuleExampleJsonV600( rule_name = "Department Head Same-Department Account Read where overdrawn", rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(ua => ua.name == \"department\" && accountAttributes.exists(aa => aa.name == \"department\" && ua.value == aa.value)) && callContext.exists(_.url.exists(_.contains(\"/accounts/\"))) && accountOpt.exists(_.balance < 0)", description = "Allow users with CanReadAccountsAtOneBank role to read overdrawn accounts in their department", + policy = "account-access", is_active = true ), AbacRuleExampleJsonV600( rule_name = "Manager Internal Network Transaction Approval", rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateTransactionRequest\") && callContext.exists(_.ipAddress.exists(ip => ip.startsWith(\"10.\") || ip.startsWith(\"192.168.\"))) && transactionRequestOpt.exists(tr => tr.status == \"PENDING\" && tr.charge.value.toDouble < 50000)", description = "Allow users with CanCreateTransactionRequest role on internal network to approve pending transaction requests under 50,000", + policy = "transaction-request", is_active = true ), AbacRuleExampleJsonV600( rule_name = "KYC Officer Customer Creation from Branch", rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanCreateCustomer\") && authenticatedUserAttributes.exists(a => a.name == \"certification\" && a.value == \"kyc_certified\") && callContext.exists(_.verb.exists(_ == \"POST\")) && callContext.exists(_.ipAddress.exists(_.startsWith(\"10.20.\"))) && customerAttributes.exists(ca => ca.name == \"onboarding_status\" && ca.value == \"pending\")", description = "Allow users with CanCreateCustomer role and KYC certification to create customers via POST from branch network (10.20.x.x) when status is pending", + policy = "customer-access", is_active = true ), AbacRuleExampleJsonV600( rule_name = "International Team Foreign Currency Transaction", rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"team\" && a.value == \"international\") && callContext.exists(_.url.exists(_.contains(\"/transactions/\"))) && transactionOpt.exists(t => t.currency != \"USD\" && t.amount < 100000) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"international_enabled\" && aa.value == \"true\"))", description = "Allow international team users with CanReadTransactionsAtOneBank role to access foreign currency transactions under 100k on international-enabled accounts", + policy = "transaction-access", is_active = true ), AbacRuleExampleJsonV600( rule_name = "Assistant with Limited Delegation Account View", rule_code = "onBehalfOfUserOpt.isDefined && onBehalfOfUserEntitlements.exists(e => e.roleName == \"CanReadAccountsAtOneBank\") && authenticatedUserAttributes.exists(a => a.name == \"assistant_of\" && onBehalfOfUserOpt.exists(u => a.value == u.userId)) && callContext.exists(_.verb.exists(_ == \"GET\")) && accountOpt.exists(a => accountAttributes.exists(aa => aa.name == \"tier\" && List(\"gold\", \"platinum\").contains(aa.value)))", description = "Allow assistants to view gold/platinum accounts via GET when acting on behalf of a user with CanReadAccountsAtOneBank role", + policy = "account-access", is_active = true ), AbacRuleExampleJsonV600( rule_name = "Fraud Analyst High-Risk Transaction Access", rule_code = "authenticatedUserEntitlements.exists(e => e.roleName == \"CanReadTransactionsAtOneBank\") && callContext.exists(c => c.verb.exists(_ == \"GET\") && c.implementedByPartialFunction.exists(_.contains(\"Transaction\"))) && transactionAttributes.exists(ta => ta.name == \"risk_score\" && ta.value.toInt >= 75) && transactionOpt.exists(_.status.exists(_ != \"COMPLETED\"))", description = "Allow users with CanReadTransactionsAtOneBank role to GET high-risk (score ≥75) non-completed transactions", + policy = "transaction-access", is_active = true ) ), @@ -5315,6 +5402,59 @@ trait APIMethods600 { } } + staticResourceDocs += ResourceDoc( + getAbacPolicies, + implementedInApiVersion, + nameOf(getAbacPolicies), + "GET", + "/management/abac-policies", + "Get ABAC Policies", + s"""Get the list of allowed ABAC policy names. + | + |ABAC rules are organized by policies. Each rule must have at least one policy assigned. + |Rules can have multiple policies (comma-separated). This endpoint returns the list of + |standardized policy names that should be used when creating or updating rules. + | + |${userAuthenticationMessage(true)} + | + |""".stripMargin, + EmptyBody, + AbacPoliciesJsonV600( + policies = List( + AbacPolicyJsonV600( + policy = "account-access", + description = "Rules for controlling access to account information" + ) + ) + ), + List( + UserNotLoggedIn, + UserHasMissingRoles, + UnknownError + ), + List(apiTagABAC), + Some(List(canGetAbacRule)) + ) + + lazy val getAbacPolicies: OBPEndpoint = { + case "management" :: "abac-policies" :: Nil JsonGet _ => { + cc => implicit val ec = EndpointContext(Some(cc)) + for { + (Full(user), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement("", user.userId, canGetAbacRule, callContext) + } yield { + val policies = Constant.ABAC_POLICIES.map { policy => + AbacPolicyJsonV600( + policy = policy, + description = Constant.ABAC_POLICY_DESCRIPTIONS.getOrElse(policy, "No description available") + ) + } + + (AbacPoliciesJsonV600(policies), HttpCode.`200`(callContext)) + } + } + } + staticResourceDocs += ResourceDoc( validateAbacRule, implementedInApiVersion, diff --git a/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala b/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala index 7e64eec36..55a92ef0f 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/JSONFactory6.0.0.scala @@ -380,6 +380,7 @@ case class CreateAbacRuleJsonV600( rule_name: String, rule_code: String, description: String, + policy: String, is_active: Boolean ) @@ -387,6 +388,7 @@ case class UpdateAbacRuleJsonV600( rule_name: String, rule_code: String, description: String, + policy: String, is_active: Boolean ) @@ -396,6 +398,7 @@ case class AbacRuleJsonV600( rule_code: String, is_active: Boolean, description: String, + policy: String, created_by_user_id: String, updated_by_user_id: String ) @@ -462,6 +465,7 @@ case class AbacRuleExampleJsonV600( rule_name: String, rule_code: String, description: String, + policy: String, is_active: Boolean ) @@ -473,6 +477,15 @@ case class AbacRuleSchemaJsonV600( notes: List[String] ) +case class AbacPolicyJsonV600( + policy: String, + description: String +) + +case class AbacPoliciesJsonV600( + policies: List[AbacPolicyJsonV600] +) + object JSONFactory600 extends CustomJsonFormats with MdcLoggable { def createRedisCallCountersJson( @@ -1086,6 +1099,7 @@ object JSONFactory600 extends CustomJsonFormats with MdcLoggable { rule_code = rule.ruleCode, is_active = rule.isActive, description = rule.description, + policy = rule.policy, created_by_user_id = rule.createdByUserId, updated_by_user_id = rule.updatedByUserId ) From 9eb984306635f9044c9b6f1323a98081e4edad3b Mon Sep 17 00:00:00 2001 From: simonredfern Date: Wed, 14 Jan 2026 09:55:02 +0100 Subject: [PATCH 41/48] Execute Policy endpoint --- .../scala/code/api/v6_0_0/APIMethods600.scala | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 677811329..d7a601178 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -5652,6 +5652,112 @@ trait APIMethods600 { } } + staticResourceDocs += ResourceDoc( + executeAbacPolicy, + implementedInApiVersion, + nameOf(executeAbacPolicy), + "POST", + "/management/abac-policies/POLICY/execute", + "Execute ABAC Policy", + s"""Execute all ABAC rules in a policy to test access control. + | + |This endpoint executes all active rules that belong to the specified policy. + |The policy uses OR logic - access is granted if at least one rule passes. + | + |This allows you to test a complete policy with specific context (authenticated user, bank, account, transaction, customer, etc.). + | + |**Documentation:** + |- ${Glossary.getGlossaryItemLink("ABAC_Simple_Guide")} - Getting started with ABAC rules + |- ${Glossary.getGlossaryItemLink("ABAC_Parameters_Summary")} - Complete list of all 18 parameters + |- ${Glossary.getGlossaryItemLink("ABAC_Object_Properties_Reference")} - Detailed property reference + |- ${Glossary.getGlossaryItemLink("ABAC_Testing_Examples")} - Testing examples and patterns + | + |You can provide optional IDs in the request body to test the policy with specific context. + | + |${userAuthenticationMessage(true)} + | + |""".stripMargin, + ExecuteAbacRuleJsonV600( + authenticated_user_id = Some("c7b6cb47-cb96-4441-8801-35b57456753a"), + on_behalf_of_user_id = Some("a3b5c123-1234-5678-9012-fedcba987654"), + user_id = Some("c7b6cb47-cb96-4441-8801-35b57456753a"), + bank_id = Some("gh.29.uk"), + account_id = Some("8ca8a7e4-6d02-48e3-a029-0b2bf89de9f0"), + view_id = Some("owner"), + transaction_request_id = Some("123456"), + transaction_id = Some("abc123"), + customer_id = Some("customer-id-123") + ), + AbacRuleResultJsonV600( + result = true + ), + List( + UserNotLoggedIn, + UserHasMissingRoles, + InvalidJsonFormat, + UnknownError + ), + List(apiTagABAC), + Some(List(canExecuteAbacRule)) + ) + + lazy val executeAbacPolicy: OBPEndpoint = { + case "management" :: "abac-policies" :: policy :: "execute" :: Nil JsonPost json -> _ => { + cc => implicit val ec = EndpointContext(Some(cc)) + for { + (Full(user), callContext) <- authenticatedAccess(cc) + _ <- NewStyle.function.hasEntitlement("", user.userId, canExecuteAbacRule, callContext) + execJson <- NewStyle.function.tryons(s"$InvalidJsonFormat", 400, callContext) { + json.extract[ExecuteAbacRuleJsonV600] + } + + // Verify the policy exists + _ <- Future { + if (Constant.ABAC_POLICIES.contains(policy)) { + Full(true) + } else { + Failure(s"Policy not found: $policy. Available policies: ${Constant.ABAC_POLICIES.mkString(", ")}") + } + } map { + unboxFullOrFail(_, callContext, s"Invalid ABAC Policy: $policy", 404) + } + + // Execute the policy with IDs - object fetching happens internally + // authenticatedUserId: can be provided in request (for testing) or defaults to actual authenticated user + // onBehalfOfUserId: optional delegation - acting on behalf of another user + // userId: the target user being evaluated (defaults to authenticated user) + effectiveAuthenticatedUserId = execJson.authenticated_user_id.getOrElse(user.userId) + + result <- Future { + val resultBox = AbacRuleEngine.executeRulesByPolicy( + policy = policy, + authenticatedUserId = effectiveAuthenticatedUserId, + onBehalfOfUserId = execJson.on_behalf_of_user_id, + userId = execJson.user_id, + callContext = callContext.getOrElse(cc), + bankId = execJson.bank_id, + accountId = execJson.account_id, + viewId = execJson.view_id, + transactionId = execJson.transaction_id, + transactionRequestId = execJson.transaction_request_id, + customerId = execJson.customer_id + ) + + resultBox match { + case Full(allowed) => + AbacRuleResultJsonV600(result = allowed) + case Failure(msg, _, _) => + AbacRuleResultJsonV600(result = false) + case Empty => + AbacRuleResultJsonV600(result = false) + } + } + } yield { + (result, HttpCode.`200`(callContext)) + } + } + } + // ============================================================================================================ // USER ATTRIBUTES v6.0.0 - Consistent with other entity attributes // ============================================================================================================ From ae599cef454767ab86ff8b39448992903d9eeb24 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Wed, 14 Jan 2026 13:30:33 +0100 Subject: [PATCH 42/48] JKS endpoint tagged OAuth and OIDC --- obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala | 2 ++ obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala b/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala index 2145c7831..93fb81537 100644 --- a/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala +++ b/obp-api/src/main/scala/code/abacrule/AbacRuleEngine.scala @@ -74,6 +74,8 @@ object AbacRuleEngine { |import com.openbankproject.commons.model._ |import code.model.dataAccess.ResourceUser |import net.liftweb.common._ + |import code.entitlement.Entitlement + |import code.api.util.CallContext | |// ABAC Rule Function |(authenticatedUser: User, authenticatedUserAttributes: List[UserAttributeTrait], authenticatedUserAuthContext: List[UserAuthContext], authenticatedUserEntitlements: List[Entitlement], onBehalfOfUserOpt: Option[User], onBehalfOfUserAttributes: List[UserAttributeTrait], onBehalfOfUserAuthContext: List[UserAuthContext], onBehalfOfUserEntitlements: List[Entitlement], userOpt: Option[User], userAttributes: List[UserAttributeTrait], bankOpt: Option[Bank], bankAttributes: List[BankAttributeTrait], accountOpt: Option[BankAccount], accountAttributes: List[AccountAttribute], transactionOpt: Option[Transaction], transactionAttributes: List[TransactionAttribute], transactionRequestOpt: Option[TransactionRequest], transactionRequestAttributes: List[TransactionRequestAttributeTrait], customerOpt: Option[Customer], customerAttributes: List[CustomerAttribute], callContext: Option[code.api.util.CallContext]) => { diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index b88d88b49..c4867e5d8 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1863,7 +1863,7 @@ trait APIMethods310 { List( UnknownError ), - List(apiTagApi)) + List(apiTagApi, apiTagOAuth, apiTagOIDC)) lazy val getObpConnectorLoopback : OBPEndpoint = { case "connector" :: "loopback" :: Nil JsonGet _ => { @@ -4111,7 +4111,7 @@ trait APIMethods310 { List( UnknownError ), - List(apiTagApi)) + List(apiTagApi, apiTagOAuth, apiTagOIDC)) lazy val getOAuth2ServerJWKsURIs: OBPEndpoint = { case "jwks-uris" :: Nil JsonGet _ => { From 423c0c17bd8cc9a1dd093bbbaf54cafbb596a1d4 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Wed, 14 Jan 2026 13:44:02 +0100 Subject: [PATCH 43/48] JKS endpoint tagged OAuth and OIDC 2 adding tags - and adding SuperAdmin Entitlement --- obp-api/src/main/scala/code/api/util/ApiTag.scala | 2 ++ .../main/scala/code/api/v6_0_0/APIMethods600.scala | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ApiTag.scala b/obp-api/src/main/scala/code/api/util/ApiTag.scala index bd4c41f01..38208d32d 100644 --- a/obp-api/src/main/scala/code/api/util/ApiTag.scala +++ b/obp-api/src/main/scala/code/api/util/ApiTag.scala @@ -18,6 +18,8 @@ object ApiTag { val apiTagTransactionRequestAttribute = ResourceDocTag("Transaction-Request-Attribute") val apiTagVrp = ResourceDocTag("VRP") val apiTagApi = ResourceDocTag("API") + val apiTagOAuth = ResourceDocTag("OAuth") + val apiTagOIDC = ResourceDocTag("OIDC") val apiTagBank = ResourceDocTag("Bank") val apiTagBankAttribute = ResourceDocTag("Bank-Attribute") val apiTagAccount = ResourceDocTag("Account") diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index d7a601178..38abee8f3 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -1074,7 +1074,15 @@ trait APIMethods600 { entitlements <- NewStyle.function.getEntitlementsByUserId(u.userId, callContext) } yield { val permissions: Option[Permission] = Views.views.vend.getPermissionForUser(u).toOption - val currentUser = UserV600(u, entitlements, permissions) + // Add SuperAdmin virtual entitlement if user is super admin + // NOTE: We ONLY use this Role in order to create CanCreateEntitlementAtAnyBank and also delete. + // Thus it is a boot straping Role. Useful to have in response so the API Manager shows Create Entitlement page to the User. + val finalEntitlements = if (APIUtil.isSuperAdmin(u.userId)) { + entitlements ::: List(Entitlement.entitlement.vend.addEntitlement("", u.userId, "SuperAdmin")) + } else { + entitlements + } + val currentUser = UserV600(u, finalEntitlements, permissions) val onBehalfOfUser = if(cc.onBehalfOfUser.isDefined) { val user = cc.onBehalfOfUser.toOption.get val entitlements = Entitlement.entitlement.vend.getEntitlementsByUserId(user.userId).headOption.toList.flatten @@ -5449,7 +5457,7 @@ trait APIMethods600 { description = Constant.ABAC_POLICY_DESCRIPTIONS.getOrElse(policy, "No description available") ) } - + (AbacPoliciesJsonV600(policies), HttpCode.`200`(callContext)) } } From 439423fc4d212c928498321581dc02af2543b2f5 Mon Sep 17 00:00:00 2001 From: simonredfern Date: Wed, 14 Jan 2026 14:08:15 +0100 Subject: [PATCH 44/48] Adding SuperAdmin Entitlement 2 --- .../scala/code/api/v6_0_0/APIMethods600.scala | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala index 38abee8f3..9dd79e45c 100644 --- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala +++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala @@ -1075,10 +1075,19 @@ trait APIMethods600 { } yield { val permissions: Option[Permission] = Views.views.vend.getPermissionForUser(u).toOption // Add SuperAdmin virtual entitlement if user is super admin - // NOTE: We ONLY use this Role in order to create CanCreateEntitlementAtAnyBank and also delete. - // Thus it is a boot straping Role. Useful to have in response so the API Manager shows Create Entitlement page to the User. val finalEntitlements = if (APIUtil.isSuperAdmin(u.userId)) { - entitlements ::: List(Entitlement.entitlement.vend.addEntitlement("", u.userId, "SuperAdmin")) + // Create a virtual SuperAdmin entitlement + val superAdminEntitlement: Entitlement = new Entitlement { + def entitlementId: String = "" + def bankId: String = "" + def userId: String = u.userId + def roleName: String = "SuperAdmin" + def createdByProcess: String = "System" + def entitlementRequestId: Option[String] = None + def groupId: Option[String] = None + def process: Option[String] = None + } + entitlements ::: List(superAdminEntitlement) } else { entitlements } From 3a264ed32676adbd2a761a6125cb2b09f120e61e Mon Sep 17 00:00:00 2001 From: karmaking Date: Wed, 14 Jan 2026 14:44:19 +0100 Subject: [PATCH 45/48] fix Github Action --- .github/workflows/auto_update_base_image.yml | 35 ------ .../build_container_develop_branch.yml | 31 ----- .../build_container_non_develop_branch.yml | 114 ------------------ .github/workflows/build_pull_request.yml | 87 ------------- .github/workflows/run_trivy.yml | 54 --------- 5 files changed, 321 deletions(-) delete mode 100644 .github/workflows/auto_update_base_image.yml delete mode 100644 .github/workflows/build_container_non_develop_branch.yml delete mode 100644 .github/workflows/build_pull_request.yml delete mode 100644 .github/workflows/run_trivy.yml diff --git a/.github/workflows/auto_update_base_image.yml b/.github/workflows/auto_update_base_image.yml deleted file mode 100644 index 3048faf15..000000000 --- a/.github/workflows/auto_update_base_image.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Regular base image update check -on: - schedule: - - cron: "0 5 * * *" - workflow_dispatch: - -env: - ## Sets environment variable - DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Docker Image Update Checker - id: baseupdatecheck - uses: lucacome/docker-image-update-checker@v2.0.0 - with: - base-image: jetty:9.4-jdk11-alpine - image: ${{ env.DOCKER_HUB_ORGANIZATION }}/obp-api:latest - - - name: Trigger build_container_develop_branch workflow - uses: actions/github-script@v6 - with: - script: | - await github.rest.actions.createWorkflowDispatch({ - owner: context.repo.owner, - repo: context.repo.repo, - workflow_id: 'build_container_develop_branch.yml', - ref: 'refs/heads/develop' - }); - if: steps.baseupdatecheck.outputs.needs-updating == 'true' diff --git a/.github/workflows/build_container_develop_branch.yml b/.github/workflows/build_container_develop_branch.yml index d3f355042..793a4d81e 100644 --- a/.github/workflows/build_container_develop_branch.yml +++ b/.github/workflows/build_container_develop_branch.yml @@ -86,34 +86,3 @@ jobs: with: name: ${{ github.sha }} path: push/ - - - name: Build the Docker image - run: | - echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin docker.io - docker build . --file .github/Dockerfile_PreBuild --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop - docker build . --file .github/Dockerfile_PreBuild_OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC - docker push docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }} --all-tags - echo docker done - - - uses: sigstore/cosign-installer@main - - - name: Write signing key to disk (only needed for `cosign sign --key`) - run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key - - - name: Sign container image - run: | - cosign sign -y --key cosign.key \ - docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop - cosign sign -y --key cosign.key \ - docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest - cosign sign -y --key cosign.key \ - docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA - cosign sign -y --key cosign.key \ - docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop-OC - cosign sign -y --key cosign.key \ - docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest-OC - env: - COSIGN_PASSWORD: "${{secrets.COSIGN_PASSWORD}}" - - - diff --git a/.github/workflows/build_container_non_develop_branch.yml b/.github/workflows/build_container_non_develop_branch.yml deleted file mode 100644 index 946d81de4..000000000 --- a/.github/workflows/build_container_non_develop_branch.yml +++ /dev/null @@ -1,114 +0,0 @@ -name: Build and publish container non develop - -on: - push: - branches: - - '*' - - '!develop' - -env: - DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} - DOCKER_HUB_REPOSITORY: obp-api - -jobs: - build: - runs-on: ubuntu-latest - services: - # Label used to access the service container - redis: - # Docker Hub image - image: redis - ports: - # Opens tcp port 6379 on the host and service container - - 6379:6379 - # Set health checks to wait until redis has started - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - steps: - - uses: actions/checkout@v4 - - name: Extract branch name - shell: bash - run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" - - name: Set up JDK 11 - uses: actions/setup-java@v4 - with: - java-version: '11' - distribution: 'adopt' - cache: maven - - name: Build with Maven - run: | - cp obp-api/src/main/resources/props/sample.props.template obp-api/src/main/resources/props/production.default.props - echo connector=star > obp-api/src/main/resources/props/test.default.props - echo starConnector_supported_types=mapped,internal >> obp-api/src/main/resources/props/test.default.props - echo hostname=http://localhost:8016 >> obp-api/src/main/resources/props/test.default.props - echo tests.port=8016 >> obp-api/src/main/resources/props/test.default.props - echo End of minimum settings >> obp-api/src/main/resources/props/test.default.props - echo payments_enabled=false >> obp-api/src/main/resources/props/test.default.props - echo importer_secret=change_me >> obp-api/src/main/resources/props/test.default.props - echo messageQueue.updateBankAccountsTransaction=false >> obp-api/src/main/resources/props/test.default.props - echo messageQueue.createBankAccounts=false >> obp-api/src/main/resources/props/test.default.props - echo allow_sandbox_account_creation=true >> obp-api/src/main/resources/props/test.default.props - echo allow_sandbox_data_import=true >> obp-api/src/main/resources/props/test.default.props - echo sandbox_data_import_secret=change_me >> obp-api/src/main/resources/props/test.default.props - echo allow_account_deletion=true >> obp-api/src/main/resources/props/test.default.props - echo allowed_internal_redirect_urls = /,/oauth/authorize >> obp-api/src/main/resources/props/test.default.props - echo transactionRequests_enabled=true >> obp-api/src/main/resources/props/test.default.props - echo transactionRequests_supported_types=SEPA,SANDBOX_TAN,FREE_FORM,COUNTERPARTY,ACCOUNT,SIMPLE >> obp-api/src/main/resources/props/test.default.props - echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo openredirects.hostname.whitlelist=http://127.0.0.1,http://localhost >> obp-api/src/main/resources/props/test.default.props - echo remotedata.secret = foobarbaz >> obp-api/src/main/resources/props/test.default.props - echo allow_public_views=true >> obp-api/src/main/resources/props/test.default.props - - echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo ACCOUNT_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo SEPA_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo FREE_FORM_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo COUNTERPARTY_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo SEPA_CREDIT_TRANSFERS_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - - echo allow_oauth2_login=true >> obp-api/src/main/resources/props/test.default.props - echo oauth2.jwk_set.url=https://www.googleapis.com/oauth2/v3/certs >> obp-api/src/main/resources/props/test.default.props - - echo ResetPasswordUrlEnabled=true >> obp-api/src/main/resources/props/test.default.props - - echo consents.allowed=true >> obp-api/src/main/resources/props/test.default.props - MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod - - - name: Save .war artifact - run: | - mkdir -p ./push - cp obp-api/target/obp-api-1.*.war ./push/ - - uses: actions/upload-artifact@v4 - with: - name: ${{ github.sha }} - path: push/ - - - name: Build the Docker image - run: | - echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin docker.io - docker build . --file .github/Dockerfile_PreBuild --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/} - docker build . --file .github/Dockerfile_PreBuild_OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC - docker push docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }} --all-tags - echo docker done - - - uses: sigstore/cosign-installer@main - - - name: Write signing key to disk (only needed for `cosign sign --key`) - run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key - - - name: Sign container image - run: | - cosign sign -y --key cosign.key \ - docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/} - cosign sign -y --key cosign.key \ - docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC - cosign sign -y --key cosign.key \ - docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA - env: - COSIGN_PASSWORD: "${{secrets.COSIGN_PASSWORD}}" - - - diff --git a/.github/workflows/build_pull_request.yml b/.github/workflows/build_pull_request.yml deleted file mode 100644 index 859d309ec..000000000 --- a/.github/workflows/build_pull_request.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Build on Pull Request - -on: - pull_request: - branches: - - '**' -env: - ## Sets environment variable - DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} - - -jobs: - build: - runs-on: ubuntu-latest - services: - # Label used to access the service container - redis: - # Docker Hub image - image: redis - ports: - # Opens tcp port 6379 on the host and service container - - 6379:6379 - # Set health checks to wait until redis has started - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 - steps: - - uses: actions/checkout@v4 - - name: Set up JDK 11 - uses: actions/setup-java@v4 - with: - java-version: '11' - distribution: 'adopt' - cache: maven - - name: Build with Maven - run: | - cp obp-api/src/main/resources/props/sample.props.template obp-api/src/main/resources/props/production.default.props - echo connector=star > obp-api/src/main/resources/props/test.default.props - echo starConnector_supported_types=mapped,internal >> obp-api/src/main/resources/props/test.default.props - echo hostname=http://localhost:8016 >> obp-api/src/main/resources/props/test.default.props - echo tests.port=8016 >> obp-api/src/main/resources/props/test.default.props - echo End of minimum settings >> obp-api/src/main/resources/props/test.default.props - echo payments_enabled=false >> obp-api/src/main/resources/props/test.default.props - echo importer_secret=change_me >> obp-api/src/main/resources/props/test.default.props - echo messageQueue.updateBankAccountsTransaction=false >> obp-api/src/main/resources/props/test.default.props - echo messageQueue.createBankAccounts=false >> obp-api/src/main/resources/props/test.default.props - echo allow_sandbox_account_creation=true >> obp-api/src/main/resources/props/test.default.props - echo allow_sandbox_data_import=true >> obp-api/src/main/resources/props/test.default.props - echo sandbox_data_import_secret=change_me >> obp-api/src/main/resources/props/test.default.props - echo allow_account_deletion=true >> obp-api/src/main/resources/props/test.default.props - echo allowed_internal_redirect_urls = /,/oauth/authorize >> obp-api/src/main/resources/props/test.default.props - echo transactionRequests_enabled=true >> obp-api/src/main/resources/props/test.default.props - echo transactionRequests_supported_types=SEPA,SANDBOX_TAN,FREE_FORM,COUNTERPARTY,ACCOUNT,SIMPLE >> obp-api/src/main/resources/props/test.default.props - echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo openredirects.hostname.whitlelist=http://127.0.0.1,http://localhost >> obp-api/src/main/resources/props/test.default.props - echo remotedata.secret = foobarbaz >> obp-api/src/main/resources/props/test.default.props - echo allow_public_views=true >> obp-api/src/main/resources/props/test.default.props - - echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo ACCOUNT_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo SEPA_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo FREE_FORM_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo COUNTERPARTY_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - echo SEPA_CREDIT_TRANSFERS_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props - - - echo allow_oauth2_login=true >> obp-api/src/main/resources/props/test.default.props - echo oauth2.jwk_set.url=https://www.googleapis.com/oauth2/v3/certs >> obp-api/src/main/resources/props/test.default.props - - echo ResetPasswordUrlEnabled=true >> obp-api/src/main/resources/props/test.default.props - - echo consents.allowed=true >> obp-api/src/main/resources/props/test.default.props - MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod - - - name: Save .war artifact - run: | - mkdir -p ./pull - cp obp-api/target/obp-api-1.*.war ./pull/ - - uses: actions/upload-artifact@v4 - with: - name: ${{ github.sha }} - path: pull/ - - - diff --git a/.github/workflows/run_trivy.yml b/.github/workflows/run_trivy.yml deleted file mode 100644 index 4636bd311..000000000 --- a/.github/workflows/run_trivy.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: scan container image - -on: - workflow_run: - workflows: - - Build and publish container develop - - Build and publish container non develop - types: - - completed -env: - ## Sets environment variable - DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} - DOCKER_HUB_REPOSITORY: obp-api - - -jobs: - build: - runs-on: ubuntu-latest - if: ${{ github.event.workflow_run.conclusion == 'success' }} - - steps: - - uses: actions/checkout@v4 - - id: trivy-db - name: Check trivy db sha - env: - GH_TOKEN: ${{ github.token }} - run: | - endpoint='/orgs/aquasecurity/packages/container/trivy-db/versions' - headers='Accept: application/vnd.github+json' - jqFilter='.[] | select(.metadata.container.tags[] | contains("latest")) | .name | sub("sha256:";"")' - sha=$(gh api -H "${headers}" "${endpoint}" | jq --raw-output "${jqFilter}") - echo "Trivy DB sha256:${sha}" - echo "::set-output name=sha::${sha}" - - uses: actions/cache@v4 - with: - path: .trivy - key: ${{ runner.os }}-trivy-db-${{ steps.trivy-db.outputs.sha }} - - name: Run Trivy vulnerability scanner - uses: aquasecurity/trivy-action@master - with: - image-ref: 'docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${{ github.sha }}' - format: 'template' - template: '@/contrib/sarif.tpl' - output: 'trivy-results.sarif' - security-checks: 'vuln' - severity: 'CRITICAL,HIGH' - timeout: '30m' - cache-dir: .trivy - - name: Fix .trivy permissions - run: sudo chown -R $(stat . -c %u:%g) .trivy - - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: 'trivy-results.sarif' \ No newline at end of file From 57f9f30a44aad48713459880105ac6ae9b4c9067 Mon Sep 17 00:00:00 2001 From: karmaking Date: Thu, 15 Jan 2026 11:45:30 +0100 Subject: [PATCH 46/48] add Github actions conditionals --- .github/workflows/auto_update_base_image.yml | 36 +++++ .../build_container_develop_branch.yml | 36 ++++- .../build_container_non_develop_branch.yml | 152 ++++++++++++++++++ .github/workflows/build_pull_request.yml | 121 ++++++++++++++ .github/workflows/run_trivy.yml | 53 ++++++ .gitignore | 1 - 6 files changed, 395 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/auto_update_base_image.yml create mode 100644 .github/workflows/run_trivy.yml diff --git a/.github/workflows/auto_update_base_image.yml b/.github/workflows/auto_update_base_image.yml new file mode 100644 index 000000000..84cec8846 --- /dev/null +++ b/.github/workflows/auto_update_base_image.yml @@ -0,0 +1,36 @@ +name: Regular base image update check +on: + schedule: + - cron: "0 5 * * *" + workflow_dispatch: + +env: + ## Sets environment variable + DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} + +jobs: + build: + runs-on: ubuntu-latest + if: github.repository == 'OpenBankProject/OBP-API' + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Docker Image Update Checker + id: baseupdatecheck + uses: lucacome/docker-image-update-checker@v2.0.0 + with: + base-image: jetty:9.4-jdk11-alpine + image: ${{ env.DOCKER_HUB_ORGANIZATION }}/obp-api:latest + + - name: Trigger build_container_develop_branch workflow + uses: actions/github-script@v6 + with: + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'build_container_develop_branch.yml', + ref: 'refs/heads/develop' + }); + if: steps.baseupdatecheck.outputs.needs-updating == 'true' diff --git a/.github/workflows/build_container_develop_branch.yml b/.github/workflows/build_container_develop_branch.yml index db6bd5160..f2905252a 100644 --- a/.github/workflows/build_container_develop_branch.yml +++ b/.github/workflows/build_container_develop_branch.yml @@ -13,7 +13,6 @@ env: DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} DOCKER_HUB_REPOSITORY: obp-api - jobs: build: runs-on: ubuntu-latest @@ -36,8 +35,8 @@ jobs: - name: Set up JDK 11 uses: actions/setup-java@v4 with: - java-version: '11' - distribution: 'adopt' + java-version: "11" + distribution: "adopt" cache: maven - name: Build with Maven run: | @@ -124,3 +123,34 @@ jobs: with: name: ${{ github.sha }} path: push/ + + - name: Build the Docker image + if: github.repository == 'OpenBankProject/OBP-API' + run: | + echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin docker.io + docker build . --file .github/Dockerfile_PreBuild --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop + docker build . --file .github/Dockerfile_PreBuild_OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC + docker push docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }} --all-tags + echo docker done + + - uses: sigstore/cosign-installer@4d14d7f17e7112af04ea6108fbb4bfc714c00390 + + - name: Write signing key to disk (only needed for `cosign sign --key`) + if: github.repository == 'OpenBankProject/OBP-API' + run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key + + - name: Sign container image + if: github.repository == 'OpenBankProject/OBP-API' + run: | + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:develop-OC + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:latest-OC + env: + COSIGN_PASSWORD: "${{secrets.COSIGN_PASSWORD}}" diff --git a/.github/workflows/build_container_non_develop_branch.yml b/.github/workflows/build_container_non_develop_branch.yml index e69de29bb..6fdd52bdd 100644 --- a/.github/workflows/build_container_non_develop_branch.yml +++ b/.github/workflows/build_container_non_develop_branch.yml @@ -0,0 +1,152 @@ +name: Build and publish container non develop + +on: + push: + branches: + - "*" + - "!develop" + +env: + DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} + DOCKER_HUB_REPOSITORY: obp-api + +jobs: + build: + runs-on: ubuntu-latest + services: + # Label used to access the service container + redis: + # Docker Hub image + image: redis + ports: + # Opens tcp port 6379 on the host and service container + - 6379:6379 + # Set health checks to wait until redis has started + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - uses: actions/checkout@v4 + - name: Extract branch name + shell: bash + run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: "11" + distribution: "adopt" + cache: maven + - name: Build with Maven + run: | + set -o pipefail + cp obp-api/src/main/resources/props/sample.props.template obp-api/src/main/resources/props/production.default.props + echo connector=star > obp-api/src/main/resources/props/test.default.props + echo starConnector_supported_types=mapped,internal >> obp-api/src/main/resources/props/test.default.props + echo hostname=http://localhost:8016 >> obp-api/src/main/resources/props/test.default.props + echo tests.port=8016 >> obp-api/src/main/resources/props/test.default.props + echo End of minimum settings >> obp-api/src/main/resources/props/test.default.props + echo payments_enabled=false >> obp-api/src/main/resources/props/test.default.props + echo importer_secret=change_me >> obp-api/src/main/resources/props/test.default.props + echo messageQueue.updateBankAccountsTransaction=false >> obp-api/src/main/resources/props/test.default.props + echo messageQueue.createBankAccounts=false >> obp-api/src/main/resources/props/test.default.props + echo allow_sandbox_account_creation=true >> obp-api/src/main/resources/props/test.default.props + echo allow_sandbox_data_import=true >> obp-api/src/main/resources/props/test.default.props + echo sandbox_data_import_secret=change_me >> obp-api/src/main/resources/props/test.default.props + echo allow_account_deletion=true >> obp-api/src/main/resources/props/test.default.props + echo allowed_internal_redirect_urls = /,/oauth/authorize >> obp-api/src/main/resources/props/test.default.props + echo transactionRequests_enabled=true >> obp-api/src/main/resources/props/test.default.props + echo transactionRequests_supported_types=SEPA,SANDBOX_TAN,FREE_FORM,COUNTERPARTY,ACCOUNT,SIMPLE >> obp-api/src/main/resources/props/test.default.props + echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo openredirects.hostname.whitlelist=http://127.0.0.1,http://localhost >> obp-api/src/main/resources/props/test.default.props + echo remotedata.secret = foobarbaz >> obp-api/src/main/resources/props/test.default.props + echo allow_public_views=true >> obp-api/src/main/resources/props/test.default.props + + echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo ACCOUNT_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo SEPA_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo FREE_FORM_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo COUNTERPARTY_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo SEPA_CREDIT_TRANSFERS_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + + echo allow_oauth2_login=true >> obp-api/src/main/resources/props/test.default.props + echo oauth2.jwk_set.url=https://www.googleapis.com/oauth2/v3/certs >> obp-api/src/main/resources/props/test.default.props + + echo ResetPasswordUrlEnabled=true >> obp-api/src/main/resources/props/test.default.props + + echo consents.allowed=true >> obp-api/src/main/resources/props/test.default.props + MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod 2>&1 | tee maven-build.log + + - name: Report failing tests (if any) + if: always() + run: | + echo "Checking build log for failing tests via grep..." + if [ ! -f maven-build.log ]; then + echo "No maven-build.log found; skipping failure scan." + exit 0 + fi + if grep -n "\*\*\* FAILED \*\*\*" maven-build.log; then + echo "Failing tests detected above." + exit 1 + else + echo "No failing tests detected in maven-build.log." + fi + + - name: Upload Maven build log + if: always() + uses: actions/upload-artifact@v4 + with: + name: maven-build-log + if-no-files-found: ignore + path: | + maven-build.log + + - name: Upload test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-reports + if-no-files-found: ignore + path: | + obp-api/target/surefire-reports/** + obp-commons/target/surefire-reports/** + **/target/scalatest-reports/** + **/target/site/surefire-report.html + **/target/site/surefire-report/* + + - name: Save .war artifact + run: | + mkdir -p ./push + cp obp-api/target/obp-api-1.*.war ./push/ + - uses: actions/upload-artifact@v4 + with: + name: ${{ github.sha }} + path: push/ + + - name: Build the Docker image + if: github.repository == 'OpenBankProject/OBP-API' + run: | + echo "${{ secrets.DOCKER_HUB_TOKEN }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin docker.io + docker build . --file .github/Dockerfile_PreBuild --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/} + docker build . --file .github/Dockerfile_PreBuild_OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA-OC --tag docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC + docker push docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }} --all-tags + echo docker done + + - uses: sigstore/cosign-installer@4d14d7f17e7112af04ea6108fbb4bfc714c00390 + + - name: Write signing key to disk (only needed for `cosign sign --key`) + if: github.repository == 'OpenBankProject/OBP-API' + run: echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > cosign.key + + - name: Sign container image + if: github.repository == 'OpenBankProject/OBP-API' + run: | + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/} + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${GITHUB_REF##*/}-OC + cosign sign -y --key cosign.key \ + docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:$GITHUB_SHA + env: + COSIGN_PASSWORD: "${{secrets.COSIGN_PASSWORD}}" diff --git a/.github/workflows/build_pull_request.yml b/.github/workflows/build_pull_request.yml index e69de29bb..e0fc7a3d4 100644 --- a/.github/workflows/build_pull_request.yml +++ b/.github/workflows/build_pull_request.yml @@ -0,0 +1,121 @@ +name: Build on Pull Request + +on: + pull_request: + branches: + - "**" +env: + ## Sets environment variable + DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} + +jobs: + build: + runs-on: ubuntu-latest + if: github.repository == 'OpenBankProject/OBP-API' + services: + # Label used to access the service container + redis: + # Docker Hub image + image: redis + ports: + # Opens tcp port 6379 on the host and service container + - 6379:6379 + # Set health checks to wait until redis has started + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: "11" + distribution: "adopt" + cache: maven + - name: Build with Maven + run: | + set -o pipefail + cp obp-api/src/main/resources/props/sample.props.template obp-api/src/main/resources/props/production.default.props + echo connector=star > obp-api/src/main/resources/props/test.default.props + echo starConnector_supported_types=mapped,internal >> obp-api/src/main/resources/props/test.default.props + echo hostname=http://localhost:8016 >> obp-api/src/main/resources/props/test.default.props + echo tests.port=8016 >> obp-api/src/main/resources/props/test.default.props + echo End of minimum settings >> obp-api/src/main/resources/props/test.default.props + echo payments_enabled=false >> obp-api/src/main/resources/props/test.default.props + echo importer_secret=change_me >> obp-api/src/main/resources/props/test.default.props + echo messageQueue.updateBankAccountsTransaction=false >> obp-api/src/main/resources/props/test.default.props + echo messageQueue.createBankAccounts=false >> obp-api/src/main/resources/props/test.default.props + echo allow_sandbox_account_creation=true >> obp-api/src/main/resources/props/test.default.props + echo allow_sandbox_data_import=true >> obp-api/src/main/resources/props/test.default.props + echo sandbox_data_import_secret=change_me >> obp-api/src/main/resources/props/test.default.props + echo allow_account_deletion=true >> obp-api/src/main/resources/props/test.default.props + echo allowed_internal_redirect_urls = /,/oauth/authorize >> obp-api/src/main/resources/props/test.default.props + echo transactionRequests_enabled=true >> obp-api/src/main/resources/props/test.default.props + echo transactionRequests_supported_types=SEPA,SANDBOX_TAN,FREE_FORM,COUNTERPARTY,ACCOUNT,SIMPLE >> obp-api/src/main/resources/props/test.default.props + echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo openredirects.hostname.whitlelist=http://127.0.0.1,http://localhost >> obp-api/src/main/resources/props/test.default.props + echo remotedata.secret = foobarbaz >> obp-api/src/main/resources/props/test.default.props + echo allow_public_views=true >> obp-api/src/main/resources/props/test.default.props + + echo SIMPLE_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo ACCOUNT_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo SEPA_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo FREE_FORM_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo COUNTERPARTY_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + echo SEPA_CREDIT_TRANSFERS_OTP_INSTRUCTION_TRANSPORT=dummy >> obp-api/src/main/resources/props/test.default.props + + echo allow_oauth2_login=true >> obp-api/src/main/resources/props/test.default.props + echo oauth2.jwk_set.url=https://www.googleapis.com/oauth2/v3/certs >> obp-api/src/main/resources/props/test.default.props + + echo ResetPasswordUrlEnabled=true >> obp-api/src/main/resources/props/test.default.props + + echo consents.allowed=true >> obp-api/src/main/resources/props/test.default.props + MAVEN_OPTS="-Xmx3G -Xss2m" mvn clean package -Pprod 2>&1 | tee maven-build.log + + - name: Report failing tests (if any) + if: always() + run: | + echo "Checking build log for failing tests via grep..." + if [ ! -f maven-build.log ]; then + echo "No maven-build.log found; skipping failure scan." + exit 0 + fi + if grep -n "\*\*\* FAILED \*\*\*" maven-build.log; then + echo "Failing tests detected above." + exit 1 + else + echo "No failing tests detected in maven-build.log." + fi + + - name: Upload Maven build log + if: always() + uses: actions/upload-artifact@v4 + with: + name: maven-build-log + if-no-files-found: ignore + path: | + maven-build.log + + - name: Upload test reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-reports + if-no-files-found: ignore + path: | + obp-api/target/surefire-reports/** + obp-commons/target/surefire-reports/** + **/target/scalatest-reports/** + **/target/site/surefire-report.html + **/target/site/surefire-report/* + + - name: Save .war artifact + run: | + mkdir -p ./pull + cp obp-api/target/obp-api-1.*.war ./pull/ + - uses: actions/upload-artifact@v4 + with: + name: ${{ github.sha }} + path: pull/ diff --git a/.github/workflows/run_trivy.yml b/.github/workflows/run_trivy.yml new file mode 100644 index 000000000..53213c031 --- /dev/null +++ b/.github/workflows/run_trivy.yml @@ -0,0 +1,53 @@ +name: scan container image + +on: + workflow_run: + workflows: + - Build and publish container develop + - Build and publish container non develop + types: + - completed +env: + ## Sets environment variable + DOCKER_HUB_ORGANIZATION: ${{ vars.DOCKER_HUB_ORGANIZATION }} + DOCKER_HUB_REPOSITORY: obp-api + +jobs: + build: + runs-on: ubuntu-latest + if: github.repository == 'OpenBankProject/OBP-API' && github.event.workflow_run.conclusion == 'success' + + steps: + - uses: actions/checkout@v4 + - id: trivy-db + name: Check trivy db sha + env: + GH_TOKEN: ${{ github.token }} + run: | + endpoint='/orgs/aquasecurity/packages/container/trivy-db/versions' + headers='Accept: application/vnd.github+json' + jqFilter='.[] | select(.metadata.container.tags[] | contains("latest")) | .name | sub("sha256:";"")' + sha=$(gh api -H "${headers}" "${endpoint}" | jq --raw-output "${jqFilter}") + echo "Trivy DB sha256:${sha}" + echo "::set-output name=sha::${sha}" + - uses: actions/cache@v4 + with: + path: .trivy + key: ${{ runner.os }}-trivy-db-${{ steps.trivy-db.outputs.sha }} + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@master + with: + image-ref: "docker.io/${{ env.DOCKER_HUB_ORGANIZATION }}/${{ env.DOCKER_HUB_REPOSITORY }}:${{ github.sha }}" + format: "template" + template: "@/contrib/sarif.tpl" + output: "trivy-results.sarif" + security-checks: "vuln" + severity: "CRITICAL,HIGH" + timeout: "30m" + cache-dir: .trivy + - name: Fix .trivy permissions + run: sudo chown -R $(stat . -c %u:%g) .trivy + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: "trivy-results.sarif" diff --git a/.gitignore b/.gitignore index 7e1e1bd93..1f8aabc66 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -.github/* *.class *.db .DS_Store From 58a9c0b834f5e133fbf5bedd9ef4ec5494a963e4 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 16 Jan 2026 12:21:09 +0100 Subject: [PATCH 47/48] refactor/build: Simplify Scala plugin configs and adjust JVM arguments --- obp-api/pom.xml | 11 ----------- pom.xml | 14 ++------------ 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/obp-api/pom.xml b/obp-api/pom.xml index 7379ff566..3aeadab1b 100644 --- a/obp-api/pom.xml +++ b/obp-api/pom.xml @@ -673,26 +673,15 @@ 4.8.1 true - incremental - true -Xms4G -Xmx12G - -Xss4m -XX:MaxMetaspaceSize=4G -XX:+UseG1GC - -XX:+TieredCompilation - -XX:TieredStopAtLevel=1 -deprecation -feature - - -language:implicitConversions - -language:reflectiveCalls - -language:postfixOps - - -Wconf:cat=deprecation&msg=auto-application:s diff --git a/pom.xml b/pom.xml index af0637b25..9969b8a19 100644 --- a/pom.xml +++ b/pom.xml @@ -134,14 +134,10 @@ ${scala.compiler} ${project.build.sourceEncoding} true - incremental - true -DpackageLinkDefs=file://${project.build.directory}/packageLinkDefs.properties - -Xms512m - -Xmx2G - -XX:+TieredCompilation - -XX:TieredStopAtLevel=1 + -Xms64m + -Xmx1024m -unchecked @@ -151,12 +147,6 @@ -deprecation --> -Ypartial-unification - - -language:implicitConversions - -language:reflectiveCalls - -language:postfixOps - - -Wconf:cat=deprecation&msg=auto-application:s From 4ffd9474df7092a15e2fbcb671459d1e56ed8e1f Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 16 Jan 2026 12:23:21 +0100 Subject: [PATCH 48/48] refactor/build: Reduce memory allocation for tests and remove parallel execution settings --- obp-api/pom.xml | 8 +------- obp-commons/pom.xml | 7 +------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/obp-api/pom.xml b/obp-api/pom.xml index 3aeadab1b..7af24246b 100644 --- a/obp-api/pom.xml +++ b/obp-api/pom.xml @@ -586,15 +586,9 @@ once . WDF TestSuite.txt - - -Drun.mode=test -XX:MaxMetaspaceSize=1G -Xms2G -Xmx4G -XX:+UseG1GC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:+UseStringDeduplication --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.jar=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED + -Drun.mode=test -XX:MaxMetaspaceSize=512m -Xms512m -Xmx512m --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.lang.invoke=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.jar=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED code.external ${maven.test.failure.ignore} - - - - - false diff --git a/obp-commons/pom.xml b/obp-commons/pom.xml index a41f81a4e..be3797110 100644 --- a/obp-commons/pom.xml +++ b/obp-commons/pom.xml @@ -113,14 +113,9 @@ once . WDF TestSuite.txt - - -Drun.mode=test -XX:MaxMetaspaceSize=1G -Xms2G -Xmx4G -XX:+UseG1GC -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:+UseStringDeduplication + -Drun.mode=test -XX:MaxMetaspaceSize=512m -Xms512m -Xmx512m code.external ${maven.test.failure.ignore} - - - - false