Skip to content

Commit

Permalink
Merge pull request #2385 from constantine2nd/develop
Browse files Browse the repository at this point in the history
Outdated agreement
  • Loading branch information
simonredfern authored May 15, 2024
2 parents 0ea39c4 + 4376c92 commit eb31062
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 14 deletions.
14 changes: 13 additions & 1 deletion obp-api/src/main/resources/i18n/lift-core.properties
Original file line number Diff line number Diff line change
Expand Up @@ -385,4 +385,16 @@ your.secret.link.is.not.valid = Looks like the invitation link is invalid. Still
privacy_policy_checkbox_text =I agree to the above Privacy Policy
privacy_policy_checkbox_label = Privacy Policy
terms_and_conditions_checkbox_text = I agree to the above Terms and Conditions
terms_and_conditions_checkbox_label = Terms and Conditions
terms_and_conditions_checkbox_label = Terms and Conditions

# Terms and conditions page
outdated.terms.button.skip = Skip
outdated.terms.button.accept = Accept
outdated.terms.warning.1 = Dear
outdated.terms.warning.2 = . We have updated our terms since you last agreed to them! Please review the text and agree if you agree!

# Privacy policy page
outdated.policy.button.skip = Skip
outdated.policy.button.accept = Accept
outdated.policy.warning.1 = Dear
outdated.policy.warning.2 = . We have updated our policy since you last agreed to them! Please review the text and agree if you agree!
40 changes: 30 additions & 10 deletions obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1038,14 +1038,34 @@ def restoreSomeSessions(): Unit = {
override def login: NodeSeq = {
// This query parameter is specific to ORY Hydra login request
val loginChallenge: Box[String] = ObpS.param("login_challenge").or(S.getSessionAttribute("login_challenge"))
def redirectUri(): String = {
loginRedirect.get match {
case Full(url) =>
loginRedirect(Empty)
url
case _ =>
homePage
def redirectUri(user: Box[ResourceUser]): String = {
val userId = user.map(_.userId).getOrElse("")
val hashedAgreementTextOfUser =
UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(userId, "terms_and_conditions")
.map(_.agreementHash).getOrElse(HashUtil.Sha256Hash("not set"))
val agreementText = getWebUiPropsValue("webui_terms_and_conditions", "not set")
val hashedAgreementText = HashUtil.Sha256Hash(agreementText)
if(hashedAgreementTextOfUser == hashedAgreementText) { // Chech terms and conditions
val hashedAgreementTextOfUser =
UserAgreementProvider.userAgreementProvider.vend.getUserAgreement(userId, "privacy_conditions")
.map(_.agreementHash).getOrElse(HashUtil.Sha256Hash("not set"))
val agreementText = getWebUiPropsValue("webui_privacy_policy", "not set")
val hashedAgreementText = HashUtil.Sha256Hash(agreementText)
if(hashedAgreementTextOfUser == hashedAgreementText) { // Check privacy policy
loginRedirect.get match {
case Full(url) =>
loginRedirect(Empty)
url
case _ =>
homePage
}
} else {
"/privacy-policy"
}
} else {
"/terms-and-conditions"
}

}
//Check the internal redirect, in case for open redirect issue.
// variable redirect is from loginRedirect, it is set-up in OAuthAuthorisation.scala as following code:
Expand Down Expand Up @@ -1131,7 +1151,7 @@ def restoreSomeSessions(): Unit = {
// User init actions
AfterApiAuth.innerLoginUserInitAction(Full(user))
logger.info("login redirect: " + loginRedirect.get)
val redirect = redirectUri()
val redirect = redirectUri(user.user.foreign)
checkInternalRedirectAndLogUserIn(preLoginState, redirect, user)
} else { // If user is NOT locked AND password is wrong => increment bad login attempt counter.
LoginAttempt.incrementBadLoginAttempts(user.getProvider(),usernameFromGui)
Expand All @@ -1151,7 +1171,7 @@ def restoreSomeSessions(): Unit = {
LoginAttempt.resetBadLoginAttempts(user.getProvider(), usernameFromGui)
val preLoginState = capturePreLoginState()
logger.info("login redirect: " + loginRedirect.get)
val redirect = redirectUri()
val redirect = redirectUri(user.user.foreign)
//This method is used for connector = kafka* || obpjvm*
//It will update the views and createAccountHolder ....
registeredUserHelper(user.getProvider(),user.username.get)
Expand All @@ -1176,7 +1196,7 @@ def restoreSomeSessions(): Unit = {

val preLoginState = capturePreLoginState()
logger.info("login redirect: " + loginRedirect.get)
val redirect = redirectUri()
val redirect = redirectUri(user.foreign)
externalUserHelper(usernameFromGui, passwordFromGui) match {
case Full(user: AuthUser) =>
LoginAttempt.resetBadLoginAttempts(user.getProvider(), usernameFromGui)
Expand Down
77 changes: 77 additions & 0 deletions obp-api/src/main/scala/code/snippet/PrivacyPolicy.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: [email protected]
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.snippet

import code.model.dataAccess.AuthUser
import code.users.UserAgreementProvider
import code.util.Helper
import code.util.Helper.MdcLoggable
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
import net.liftweb.http.{S, SHtml}
import net.liftweb.util.CssSel
import net.liftweb.util.Helpers._

class PrivacyPolicy extends MdcLoggable {

def updateForm: CssSel = {

def submitButtonDefense(): Unit = {
updateUserAgreement()
}

def skipButtonDefense(): Unit = {
S.redirectTo("/")
}

def displayContent = {
if(AuthUser.currentUser.isDefined) {
"block"
} else {
"none"
}
}

def update = {
val username = AuthUser.currentUser.flatMap(_.user.foreign.map(_.name)).getOrElse("")
"#privacy-policy-username *" #> username &
"type=submit" #> SHtml.submit(s"${Helper.i18n("outdated.terms.button.accept")}", () => submitButtonDefense) &
"type=reset" #> SHtml.submit(s"${Helper.i18n("outdated.terms.button.skip")}", () => skipButtonDefense) &
"#form_privacy_policy [style]" #> s"display: $displayContent;"
}
update
}

private def updateUserAgreement() = {
if(AuthUser.currentUser.isDefined) {
val agreementText = getWebUiPropsValue("webui_privacy_policy", "not set")
UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement(
AuthUser.currentUser.flatMap(_.user.foreign.map(_.userId)).getOrElse(""), "privacy_conditions", agreementText)
S.redirectTo("/")
}
}

}
78 changes: 78 additions & 0 deletions obp-api/src/main/scala/code/snippet/TermsAndConditions.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: [email protected]
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.snippet

import code.model.dataAccess.AuthUser
import code.users.UserAgreementProvider
import code.util.Helper
import code.util.Helper.MdcLoggable
import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue
import net.liftweb.http.{S, SHtml}
import net.liftweb.util.CssSel
import net.liftweb.util.Helpers._

class TermsAndConditions extends MdcLoggable {

def updateForm: CssSel = {

def submitButtonDefense(): Unit = {
updateUserAgreement()
}

def skipButtonDefense(): Unit = {
S.redirectTo("/")
}

def displayContent = {
if(AuthUser.currentUser.isDefined) {
"block"
} else {
"none"
}
}

def update = {
val username = AuthUser.currentUser.flatMap(_.user.foreign.map(_.name)).getOrElse("")
"#terms-and-conditions-username *" #> username &
"type=submit" #> SHtml.submit(s"${Helper.i18n("outdated.policy.button.accept")}", () => submitButtonDefense) &
"type=reset" #> SHtml.submit(s"${Helper.i18n("outdated.policy.button.skip")}", () => skipButtonDefense) &
"#form_terms_and_conditions [style]" #> s"display: $displayContent;"
}
update
}

private def updateUserAgreement() = {
if(AuthUser.currentUser.isDefined) {
val agreementText = getWebUiPropsValue("webui_terms_and_conditions", "not set")
// val hashedAgreementText = HashUtil.Sha256Hash(agreementText)
UserAgreementProvider.userAgreementProvider.vend.createOrUpdateUserAgreement(
AuthUser.currentUser.flatMap(_.user.foreign.map(_.userId)).getOrElse(""), "terms_and_conditions", agreementText)
S.redirectTo("/")
}
}

}
9 changes: 9 additions & 0 deletions obp-api/src/main/scala/code/users/UserAgreement.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import code.api.util.HashUtil
import code.util.UUIDString
import net.liftweb.common.{Box, Empty, Full}
import net.liftweb.mapper._
import net.liftweb.common.Box.tryo

object MappedUserAgreementProvider extends UserAgreementProvider {
override def createOrUpdateUserAgreement(userId: String, agreementType: String, agreementText: String): Box[UserAgreement] = {
Expand Down Expand Up @@ -75,5 +76,13 @@ class UserAgreement extends UserAgreementTrait with LongKeyedMapper[UserAgreemen

object UserAgreement extends UserAgreement with LongKeyedMetaMapper[UserAgreement] {
override def dbIndexes: List[BaseIndex[UserAgreement]] = UniqueIndex(UserAgreementId) :: super.dbIndexes
override def beforeSave = List(
agreement =>
tryo {
val hash = HashUtil.Sha256Hash(agreement.agreementText)
agreement.AgreementHash(hash ).save
}
)

}

7 changes: 6 additions & 1 deletion obp-api/src/main/scala/code/util/Helper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,12 @@ object Helper extends Loggable {
*/
def isValidInternalRedirectUrl(url: String) : Boolean = {
//set the default value is "/" and "/oauth/authorize"
val validUrls = List("/","/oauth/authorize","/consumer-registration","/dummy-user-tokens","/create-sandbox-account", "/add-user-auth-context-update-request","/otp")
val validUrls = List(
"/","/oauth/authorize","/consumer-registration",
"/dummy-user-tokens","/create-sandbox-account",
"/add-user-auth-context-update-request","/otp",
"/terms-and-conditions", "/privacy-policy"
)

//case1: OBP-API login: url = "/"
//case2: API-Explore oauth login: url = "/oauth/authorize?oauth_token=V0JTCDYXWUNTXDZ3VUDNM1HE3Q1PZR2WJ4PURXQA&logUserOut=false"
Expand Down
13 changes: 12 additions & 1 deletion obp-api/src/main/webapp/privacy-policy.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,18 @@
<div data-lift="surround?with=default;at=content">
<div data-lift="WebUI.privacyPolicyText">
<div id="api_documentation_div">
<div id="api_documentation_content" tabindex="-1">
<form id="form_privacy_policy" method="post" data-lift="PrivacyPolicy.updateForm">
<div class="row" >
<div><lift:loc locid="outdated.policy.warning.1">Dear</lift:loc> <em id="privacy-policy-username"></em> <lift:loc locid="outdated.policy.warning.2">. We have updated our policy since you last agreed to them! Please review the text and agree if you agree!</lift:loc></div>
<div class="col-xs-6">
<input type="reset" value="Skip" class="btn btn-default pull-right" tabindex="0"/>
</div>
<div class="col-xs-6">
<input type="submit" value="accept terms" class="btn btn-default" tabindex="0"/>
</div>
</div>
</form>
<div>
<div id="privacy-policy-page"></div>
</div>
</div>
Expand Down
13 changes: 12 additions & 1 deletion obp-api/src/main/webapp/terms-and-conditions.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,18 @@
<div data-lift="surround?with=default;at=content">
<div data-lift="WebUI.termsAndConditionsText">
<div id="api_documentation_div">
<div id="api_documentation_content" tabindex="-1">
<form id="form_terms_and_conditions" method="post" data-lift="TermsAndConditions.updateForm">
<div class="row" >
<div><lift:loc locid="outdated.terms.warning.1">Dear</lift:loc> <em id="terms-and-conditions-username"></em> <lift:loc locid="outdated.terms.warning.2">. We have updated our terms since you last agreed to them! Please review the text and agree if you agree!</lift:loc></div>
<div class="col-xs-6">
<input type="reset" value="Skip" class="btn btn-default pull-right" tabindex="0"/>
</div>
<div class="col-xs-6">
<input type="submit" value="accept terms" class="btn btn-default" tabindex="0"/>
</div>
</div>
</form>
<div>
<div id="terms-and-conditions-page"></div>
</div>
</div>
Expand Down

0 comments on commit eb31062

Please sign in to comment.