/src/main/scala/code/model/dataAccess/AuthUser.scala
Scala | 829 lines | 594 code | 95 blank | 140 comment | 100 complexity | 8831def15ae0929ea6b50ab71ef30227 MD5 | raw file
- /**
- Open Bank Project - API
- Copyright (C) 2011-2016, TESOBE Ltd
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- Email: contact@tesobe.com
- TESOBE Ltd
- Osloerstrasse 16/17
- Berlin 13359, Germany
- This product includes software developed at
- TESOBE (http://www.tesobe.com/)
- by
- Simon Redfern : simon AT tesobe DOT com
- Stefan Bethge : stefan AT tesobe DOT com
- Everett Sochowski : everett AT tesobe DOT com
- Ayoub Benali: ayoub AT tesobe DOT com
- */
- package code.model.dataAccess
- import java.util.UUID
- import code.api.util.APIUtil.isValidStrongPassword
- import code.api.util.{APIUtil, ErrorMessages}
- import code.api.{DirectLogin, OAuthHandshake}
- import code.bankconnectors.{Connector, InboundUser}
- import net.liftweb.common._
- import net.liftweb.http._
- import net.liftweb.mapper._
- import net.liftweb.util.Mailer.{BCC, From, Subject, To}
- import net.liftweb.util._
- import scala.xml.{NodeSeq, Text}
- import code.loginattempts.LoginAttempt
- import code.users.Users
- import code.util.Helper
- import net.liftweb.util
- /**
- * An O-R mapped "User" class that includes first name, last name, password
- *
- *
- * // TODO Document the difference between this and AuthUser / ResourceUser
- *
- */
- class AuthUser extends MegaProtoUser[AuthUser] with Logger {
- def getSingleton = AuthUser // what's the "meta" server
- object user extends MappedLongForeignKey(this, ResourceUser)
- /**
- * The username field for the User.
- */
- lazy val username: userName = new userName()
- class userName extends MappedString(this, 64) {
- override def displayName = S.?("username")
- override def dbIndexed_? = true
- override def validations = valUnique(S.?("unique.username")) _ :: super.validations
- override val fieldId = Some(Text("txtUsername"))
- }
- override lazy val password = new MyPasswordNew
-
- class MyPasswordNew extends MappedPassword(this) {
-
- override def displayName = fieldOwner.passwordDisplayName
-
- private var passwordValue = ""
- private var invalidPw = false
- private var invalidMsg = ""
-
- override def setFromAny(f: Any): String = {
- f match {
- case a: Array[String] if (a.length == 2 && a(0) == a(1)) => {
- passwordValue = a(0).toString;
- if (isValidStrongPassword(passwordValue))
- invalidPw = false
- else {
- invalidPw = true
- invalidMsg = S.?(ErrorMessages.InvalidStrongPasswordFormat)
- }
- this.set(a(0))
- }
- case l: List[String] if (l.length == 2 && l.head == l(1)) => {
- passwordValue = l(0).toString;
- if (isValidStrongPassword(passwordValue))
- invalidPw = false
- else {
- invalidPw = true
- invalidMsg = S.?(ErrorMessages.InvalidStrongPasswordFormat)
- }
-
- this.set(l.head)
- }
- case _ => {
- invalidPw = true;
- invalidMsg = S.?("passwords.do.not.match")
- }
- }
- get
- }
-
- override def validate: List[FieldError] = {
- if (super.validate.nonEmpty) super.validate
- else if (!invalidPw && password.get != "*") Nil
- else if (invalidPw) List(FieldError(this, Text(invalidMsg)))
- else List(FieldError(this, Text(S.?("password.must.be.set"))))
- }
-
- }
- /**
- * The provider field for the User.
- */
- lazy val provider: userProvider = new userProvider()
- class userProvider extends MappedString(this, 64) {
- override def displayName = S.?("provider")
- override val fieldId = Some(Text("txtProvider"))
- }
- def getProvider() = {
- if(provider.get == null) {
- Props.get("hostname","")
- } else if ( provider.get == "" || provider.get == Props.get("hostname","") ) {
- Props.get("hostname","")
- } else {
- provider.get
- }
- }
- def createUnsavedResourceUser() : ResourceUser = {
- val user = Users.users.vend.createUnsavedResourceUser(getProvider(), Some(username), Some(username), Some(email), None).get
- user
- }
- def getResourceUsersByEmail(userEmail: String) : List[ResourceUser] = {
- Users.users.vend.getUserByEmail(userEmail) match {
- case Full(userList) => userList
- case Empty => List()
- }
- }
- def getResourceUsers(): List[ResourceUser] = {
- Users.users.vend.getAllUsers match {
- case Full(userList) => userList
- case Empty => List()
- }
- }
- def getResourceUserByUsername(username: String) : Box[ResourceUser] = {
- Users.users.vend.getUserByUserName(username)
- }
- override def save(): Boolean = {
- if(! (user defined_?)){
- info("user reference is null. We will create a ResourceUser")
- val resourceUser = createUnsavedResourceUser()
- val savedUser = Users.users.vend.saveResourceUser(resourceUser)
- user(savedUser) //is this saving resourceUser into a user field?
- }
- else {
- info("user reference is not null. Trying to update the ResourceUser")
- Users.users.vend.getResourceUserByResourceUserId(user.get).map{ u =>{
- info("API User found ")
- u.name_(username)
- .email(email)
- .providerId(username)
- .save
- }
- }
- }
- super.save()
- }
- override def delete_!(): Boolean = {
- user.obj.map(u => Users.users.vend.deleteResourceUser(u.id))
- super.delete_!
- }
- // Regex to validate an email address as per W3C recommendations: https://www.w3.org/TR/html5/forms.html#valid-e-mail-address
- private val emailRegex = """^[a-zA-Z0-9\.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$""".r
- def isEmailValid(e: String): Boolean = e match{
- case null => false
- case e if e.trim.isEmpty => false
- case e if emailRegex.findFirstMatchIn(e).isDefined => true
- case _ => false
- }
- // Override the validate method of MappedEmail class
- // There's no way to override the default emailPattern from MappedEmail object
- override lazy val email = new MyEmail(this, 48) {
- override def validations = super.validations
- override def dbIndexed_? = false
- override def validate = if (isEmailValid(i_is_!)) Nil else List(FieldError(this, Text(S.?("invalid.email.address"))))
- }
- }
- /**
- * The singleton that has methods for accessing the database
- */
- object AuthUser extends AuthUser with MetaMegaProtoUser[AuthUser]{
- import net.liftweb.util.Helpers._
- /**Marking the locked state to show different error message */
- val usernameLockedStateCode = Long.MaxValue
- val connector = Props.get("connector").openOrThrowException("no connector set")
- override def emailFrom = Props.get("mail.users.userinfo.sender.address", "sender-not-set")
- override def screenWrap = Full(<lift:surround with="default" at="content"><lift:bind /></lift:surround>)
- // 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)
- // If we want to validate email addresses set this to false
- override def skipEmailValidation = Props.getBool("authUser.skipEmailValidation", true)
- override def loginXhtml = {
- val loginXml = Templates(List("templates-hidden","_login")).map({
- "form [action]" #> {S.uri} &
- "#loginText * " #> {S.?("log.in")} &
- "#usernameText * " #> {S.?("username")} &
- "#passwordText * " #> {S.?("password")} &
- "autocomplete=off [autocomplete] " #> APIUtil.getAutocompleteValue &
- "#recoverPasswordLink * " #> {
- "a [href]" #> {lostPasswordPath.mkString("/", "/", "")} &
- "a *" #> {S.?("recover.password")}
- } &
- "#SignUpLink * " #> {
- "a [href]" #> {AuthUser.signUpPath.foldLeft("")(_ + "/" + _)} &
- "a *" #> {S.?("sign.up")}
- }
- })
- <div>{loginXml getOrElse NodeSeq.Empty}</div>
- }
- /**
- * Find current user
- */
- def getCurrentUserUsername: String = {
- for {
- current <- AuthUser.currentUser
- username <- tryo{current.username.get}
- if (username.nonEmpty)
- } yield {
- return username
- }
- for {
- current <- OAuthHandshake.getUser
- username <- tryo{current.name}
- if (username.nonEmpty)
- } yield {
- return username
- }
- for {
- current <- DirectLogin.getUser
- username <- tryo{current.name}
- if (username.nonEmpty)
- } yield {
- return username
- }
- return ""
- }
- /**
- * Find current ResourceUser_UserId from AuthUser, reference the @getCurrentUserUsername
- * This method has no parameters, it depends on different login types:
- * AuthUser: AuthUser.currentUser
- * OAuthHandshake: OAuthHandshake.getUser
- * DirectLogin: DirectLogin.getUser
- * to get the current Resourceuser.userId feild.
- *
- * Note: resourceuser has two ids: id(Long) and userid_(String),
- * This method return userid_(String).
- */
- def getCurrentResourceUserUserId: String = {
- for {
- current <- AuthUser.currentUser
- user <- Users.users.vend.getUserByResourceUserId(current.user.get)
- } yield {
- return user.userId
- }
- for {
- current <- OAuthHandshake.getUser
- userId <- tryo{current.userId}
- if (userId.nonEmpty)
- } yield {
- return userId
- }
- for {
- current <- DirectLogin.getUser
- userId <- tryo{current.userId}
- if (userId.nonEmpty)
- } yield {
- return userId
- }
- return ""
- }
- /**
- * The string that's generated when the user name is not found. By
- * default: S.?("email.address.not.found")
- * The function is overridden in order to prevent leak of information at password reset page if username / email exists or do not exist.
- * I.e. we want to prevent case in which an anonymous user can get information from the message does some username/email exist or no in our system.
- */
- override def userNameNotFoundString: String = "Thank you. If we found a matching user, password reset instructions have been sent."
- /**
- * Overridden to use the hostname set in the props file
- */
- override def sendPasswordReset(name: String) {
- findUserByUsername(name) match {
- case Full(user) if user.validated_? =>
- user.resetUniqueId().save
- val resetLink = Props.get("hostname", "ERROR")+
- passwordResetPath.mkString("/", "/", "/")+urlEncode(user.getUniqueId())
- Mailer.sendMail(From(emailFrom),Subject(passwordResetEmailSubject),
- To(user.getEmail) ::
- generateResetEmailBodies(user, resetLink) :::
- (bccEmail.toList.map(BCC(_))) :_*)
- S.notice(S.?(userNameNotFoundString))
- S.redirectTo(homePage)
- case Full(user) =>
- sendValidationEmail(user)
- S.notice(S.?("account.validation.resent"))
- S.redirectTo(homePage)
- case _ => S.error(userNameNotFoundString)
- }
- }
- override def lostPasswordXhtml = {
- <div id="authorizeSection">
- <div id="userAccess">
- <div class="account account-in-content">
- Enter your email address or username and we'll email you a link to reset your password
- <form class="forgotPassword" action={S.uri} method="post">
- <div class="field username">
- <label>Username or email address</label> <user:email />
- </div>
- <div class="field buttons">
- <div class="button button-field">
- <user:submit />
- </div>
- </div>
- </form>
- </div>
- </div>
- </div>
- }
- override def lostPassword = {
- bind("user", lostPasswordXhtml,
- "email" -> SHtml.text("", sendPasswordReset _),
- "submit" -> lostPasswordSubmitButton(S.?("submit")))
- }
- //override def def passwordResetMailBody(user: TheUserType, resetLink: String): Elem = { }
- /**
- * Overriden to use the hostname set in the props file
- */
- override def sendValidationEmail(user: TheUserType) {
- val resetLink = Props.get("hostname", "ERROR")+"/"+validateUserPath.mkString("/")+
- "/"+urlEncode(user.getUniqueId())
- val email: String = user.getEmail
- val msgXml = signupMailBody(user, resetLink)
- Mailer.sendMail(From(emailFrom),Subject(signupMailSubject),
- To(user.getEmail) ::
- generateValidationEmailBodies(user, resetLink) :::
- (bccEmail.toList.map(BCC(_))) :_* )
- }
- /**
- * Set this to redirect to a certain page after a failed login
- */
- object failedLoginRedirect extends SessionVar[Box[String]](Empty) {
- override lazy val __nameSalt = Helpers.nextFuncName
- }
- def agreeTerms = {
- val url = Props.get("webui_agree_terms_url", "")
- if (url.isEmpty) {
- s""
- } else {
- scala.xml.Unparsed(s"""<tr><td colspan="2"><input type="checkbox" id="agree-terms-input" /><span id="agree-terms-text">I hereby agree to the <a href="$url" title="T & C">Terms and Conditions</a></span></td></tr>""")
- }
- }
- override def signupXhtml (user:AuthUser) = {
- <div id="authorizeSection" class="signupSection">
- <div class="signup-error"><span class="lift:Msg?id=signup"/></div>
- <div>
- <form id="signupForm" method="post" action={S.uri}>
- <table>
- <tr>
- <td colspan="2">{ S.?("sign.up") }</td>
- </tr>
- {localForm(user, false, signupFields)}
- {agreeTerms}
- <tr>
- <td> </td>
- <td><user:submit/></td>
- </tr>
- </table>
- </form>
- </div>
- </div>
- }
- def userLoginFailed = {
- info("failed: " + failedLoginRedirect.get)
- // variable redir is from failedLoginRedirect, it is set-up in OAuthAuthorisation.scala as following code:
- // val currentUrl = S.uriAndQueryString.getOrElse("/")
- // AuthUser.failedLoginRedirect.set(Full(Helpers.appendParams(currentUrl, List((FailedLoginParam, "true")))))
- val redir = failedLoginRedirect.get
- //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 = S.uriAndQueryString.getOrElse("/")
- // AuthUser.loginRedirect.set(Full(Helpers.appendParams(currentUrl, List((LogUserOutParam, "false")))))
- if (Helper.isValidInternalRedirectUrl(redir.toString)) {
- S.redirectTo(redir.toString)
- } else {
- S.error(S.?(ErrorMessages.InvalidInternalRedirectUrl))
- info(ErrorMessages.InvalidInternalRedirectUrl + loginRedirect.get)
- }
- S.error("login", S.?("Invalid Username or Password"))
- }
- def getResourceUserId(username: String, password: String): Box[Long] = {
- findUserByUsername(username) match {
- case Full(user) if (user.getProvider() == Props.get("hostname","")) =>
- if (
- user.validated_? &&
- // User is NOT locked AND the password is good
- ! LoginAttempt.userIsLocked(username) &&
- user.testPassword(Full(password)))
- {
- // We logged in correctly, so reset badLoginAttempts counter (if it exists)
- LoginAttempt.resetBadLoginAttempts(username)
- Full(user.user) // Return the user.
- }
- // User is unlocked AND password is bad
- else if (
- user.validated_? &&
- ! LoginAttempt.userIsLocked(username) &&
- ! user.testPassword(Full(password))
- ) {
- LoginAttempt.incrementBadLoginAttempts(username)
- Empty
- }
- // User is locked
- else if (LoginAttempt.userIsLocked(username))
- {
- LoginAttempt.incrementBadLoginAttempts(username)
- info(ErrorMessages.UsernameHasBeenLocked)
- //TODO need to fix, use Failure instead, it is used to show the error message to the GUI
- Full(usernameLockedStateCode)
- }
- else {
- // Nothing worked, so just increment bad login attempts
- LoginAttempt.incrementBadLoginAttempts(username)
- Empty
- }
- case Full(user) if (user.getProvider() != Props.get("hostname","")) =>
- connector match {
- case Helper.matchAnyKafka() if ( Props.getBool("kafka.user.authentication", false) &&
- ! LoginAttempt.userIsLocked(username) ) =>
- val userId = for { kafkaUser <- getUserFromConnector(username, password)
- kafkaUserId <- tryo{kafkaUser.user} } yield {
- LoginAttempt.resetBadLoginAttempts(username)
- kafkaUserId.toLong
- }
- userId match {
- case Full(l:Long) => Full(l)
- case _ =>
- LoginAttempt.incrementBadLoginAttempts(username)
- Empty
- }
- case "obpjvm" if ( Props.getBool("obpjvm.user.authentication", false) &&
- ! LoginAttempt.userIsLocked(username) ) =>
- val userId = for { obpjvmUser <- getUserFromConnector(username, password)
- obpjvmUserId <- tryo{obpjvmUser.user} } yield {
- LoginAttempt.resetBadLoginAttempts(username)
- obpjvmUserId.toLong
- }
- userId match {
- case Full(l:Long) => Full(l)
- case _ =>
- LoginAttempt.incrementBadLoginAttempts(username)
- Empty
- }
- case _ =>
- LoginAttempt.incrementBadLoginAttempts(username)
- Empty
- }
- case _ =>
- LoginAttempt.incrementBadLoginAttempts(username)
- Empty
- }
- }
- def getUserFromConnector(name: String, password: String):Box[AuthUser] = {
- Connector.connector.vend.getUser(name, password) match {
- case Full(InboundUser(extEmail, extPassword, extUsername)) => {
- info("external user authenticated. login redir: " + loginRedirect.get)
- val redir = loginRedirect.get match {
- case Full(url) =>
- loginRedirect(Empty)
- url
- case _ =>
- homePage
- }
- val extProvider = connector
- val user = findUserByUsername(name) match {
- // Check if the external user is already created locally
- case Full(user) if user.validated_?
- // && user.provider == extProvider
- => {
- // Return existing user if found
- info("external user already exists locally, using that one")
- user
- }
- // If not found, create new user
- case _ => {
- // Create AuthUser using fetched data from Kafka
- // assuming that user's email is always validated
- info("external user "+ extEmail +" does not exist locally, creating one")
- val newUser = AuthUser.create
- .firstName(extUsername)
- .email(extEmail)
- .username(extUsername)
- // No need to store password, so store dummy string instead
- .password(UUID.randomUUID().toString)
- .provider(extProvider)
- .validated(true)
- // Save the user in order to be able to log in
- newUser.save()
- // Return created user
- newUser
- }
- }
- Full(user)
- }
- case _ => {
- Empty
- }
- }
- }
- //overridden to allow a redirection if login fails
- override def login = {
- def loginAction = {
- if (S.post_?) {
- val usernameFromGui = S.param("username").getOrElse("")
- val passwordFromGui = S.param("password").getOrElse("")
- findUserByUsername(usernameFromGui) match {
- // Check if user came from localhost and
- // if User is NOT locked and password is good
- case Full(user) if user.validated_? &&
- user.getProvider() == Props.get("hostname","") &&
- ! LoginAttempt.userIsLocked(usernameFromGui) &&
- user.testPassword(Full(passwordFromGui)) => {
- // Reset any bad attempts
- LoginAttempt.resetBadLoginAttempts(usernameFromGui)
- val preLoginState = capturePreLoginState()
- info("login redir: " + loginRedirect.get)
- val redir = loginRedirect.get match {
- case Full(url) =>
- loginRedirect(Empty)
- url
- case _ =>
- homePage
- }
- registeredUserHelper(user.username)
- //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 = S.uriAndQueryString.getOrElse("/")
- // AuthUser.loginRedirect.set(Full(Helpers.appendParams(currentUrl, List((LogUserOutParam, "false")))))
- if (Helper.isValidInternalRedirectUrl(redir.toString)) {
- logUserIn(user, () => {
- S.notice(S.?("logged.in"))
- preLoginState()
- S.redirectTo(redir)
- })
- } else {
- S.error(S.?(ErrorMessages.InvalidInternalRedirectUrl))
- info(ErrorMessages.InvalidInternalRedirectUrl + loginRedirect.get)
- }
- }
- // Check if user came from kafka/obpjvm and
- // if User is NOT locked. Then check username and password
- // from connector in case they changed on the south-side
- case Full(user) if user.validated_? &&
- user.getProvider() != Props.get("hostname","") &&
- ! LoginAttempt.userIsLocked(usernameFromGui) &&
- testExternalPassword(Full(user.username.get), Full(passwordFromGui)).getOrElse(false) => {
- // Reset any bad attempts
- LoginAttempt.resetBadLoginAttempts(usernameFromGui)
- val preLoginState = capturePreLoginState()
- info("login redir: " + loginRedirect.get)
- val redir = loginRedirect.get match {
- case Full(url) =>
- loginRedirect(Empty)
- url
- case _ =>
- homePage
- }
- registeredUserHelper(user.username)
- //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 = S.uriAndQueryString.getOrElse("/")
- // AuthUser.loginRedirect.set(Full(Helpers.appendParams(currentUrl, List((LogUserOutParam, "false")))))
- if (Helper.isValidInternalRedirectUrl(redir.toString)) {
- logUserIn(user, () => {
- S.notice(S.?("logged.in"))
- preLoginState()
- S.redirectTo(redir)
- })
- } else {
- S.error(S.?(ErrorMessages.InvalidInternalRedirectUrl))
- info(ErrorMessages.InvalidInternalRedirectUrl + loginRedirect.get)
- }
- }
- // If user is unlocked AND bad password, increment bad login attempt counter.
- case Full(user) if user.validated_? &&
- user.getProvider() == Props.get("hostname","") &&
- ! LoginAttempt.userIsLocked(usernameFromGui) &&
- ! user.testPassword(Full(passwordFromGui)) =>
- LoginAttempt.incrementBadLoginAttempts(usernameFromGui)
- S.error(S.?("Invalid Login Credentials")) // TODO constant / i18n for this string
- // If user is locked, send the error to GUI
- case Full(user) if LoginAttempt.userIsLocked(usernameFromGui) =>
- LoginAttempt.incrementBadLoginAttempts(usernameFromGui)
- S.error(S.?(ErrorMessages.UsernameHasBeenLocked))
- case Full(user) if !user.validated_? =>
- S.error(S.?("account.validation.error")) // Note: This does not seem to get hit when user is not validated.
- // If not found locally, try to authenticate user via Kafka, if enabled in props
- case Empty if (connector.startsWith("kafka") || connector == "obpjvm") &&
- (Props.getBool("kafka.user.authentication", false) ||
- Props.getBool("obpjvm.user.authentication", false)) =>
- val preLoginState = capturePreLoginState()
- info("login redir: " + loginRedirect.get)
- val redir = loginRedirect.get match {
- case Full(url) =>
- loginRedirect(Empty)
- url
- case _ =>
- homePage
- }
- for {
- user_ <- externalUserHelper(usernameFromGui, passwordFromGui)
- } yield {
- user_
- } match {
- case u:AuthUser =>
- LoginAttempt.resetBadLoginAttempts(usernameFromGui)
- //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 = S.uriAndQueryString.getOrElse("/")
- // AuthUser.loginRedirect.set(Full(Helpers.appendParams(currentUrl, List((LogUserOutParam, "false")))))
- if (Helper.isValidInternalRedirectUrl(redir.toString)) {
- logUserIn(u, () => {
- S.notice(S.?("logged.in"))
- preLoginState()
- S.redirectTo(redir)
- })
- } else {
- S.error(S.?(ErrorMessages.InvalidInternalRedirectUrl))
- info(ErrorMessages.InvalidInternalRedirectUrl + loginRedirect.get)
- }
- case _ =>
- LoginAttempt.incrementBadLoginAttempts(username)
- Empty
- }
- case _ =>
- LoginAttempt.incrementBadLoginAttempts(usernameFromGui)
- S.error(S.?(ErrorMessages.UnexpectedErrorDuringLogin)) // Note we hit this if user has not clicked email validation link
- }
- }
- }
- // In this function we bind submit button to loginAction function.
- // In case that unique token of submit button cannot be paired submit action will be omitted.
- // Implemented in order to prevent a CSRF attack
- def insertSubmitButton = {
- scala.xml.XML.loadString(loginSubmitButton(S.?("Login"), loginAction _).toString().replace("type=\"submit\"","class=\"submit\" type=\"submit\""))
- }
- bind("user", loginXhtml,
- "submit" -> insertSubmitButton)
- }
- def testExternalPassword(usernameFromGui: Box[String], passwordFromGui: Box[String]): Box[Boolean] = {
- if (connector.startsWith("kafka") || connector == "obpjvm") {
- val res = for {
- username <- usernameFromGui
- password <- passwordFromGui
- user <- getUserFromConnector(username, password)
- } yield user match {
- case user:AuthUser => true
- case _ => false
- }
- res
- } else Empty
- }
- def externalUserHelper(name: String, password: String): Box[AuthUser] = {
- if (connector.startsWith("kafka") || connector == "obpjvm") {
- for {
- user <- getUserFromConnector(name, password)
- u <- Users.users.vend.getUserByUserName(username)
- v <- tryo {Connector.connector.vend.updateUserAccountViews(u)}
- } yield {
- user
- }
- } else Empty
- }
- def registeredUserHelper(username: String) = {
- if (connector.startsWith("kafka") || connector == "obpjvm") {
- for {
- u <- Users.users.vend.getUserByUserName(username)
- v <- tryo {Connector.connector.vend.updateUserAccountViews(u)}
- } yield v
- }
- }
- protected def findUserByUsername(name: String): Box[TheUserType] = {
- find(By(this.username, name))
- }
- //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 = S.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 _ =>
- homePage
- }
- if (Helper.isValidInternalRedirectUrl(redir.toString)) {
- actionsAfterSignup(theUser, () => {
- S.redirectTo(redir)
- })
- } else {
- S.error(S.?(ErrorMessages.InvalidInternalRedirectUrl))
- info(ErrorMessages.InvalidInternalRedirectUrl + loginRedirect.get)
- }
- case xs =>
- xs.foreach(e => S.error("signup", e.msg))
- signupFunc(Full(innerSignup _))
- }
- }
- def innerSignup = bind("user",
- signupXhtml(theUser),
- "submit" -> signupSubmitButton(S.?("sign.up"), testSignup _))
- innerSignup
- }
- }