Merge pull request #152 from pbozin/develop

Switch to using username instead of email as unique user identifier
This commit is contained in:
Simon Redfern 2016-09-08 08:04:51 +02:00 committed by GitHub
commit 7f2ef47897
16 changed files with 170 additions and 146 deletions

View File

@ -303,7 +303,7 @@ object DirectLogin extends RestHelper with Loggable {
val user = token.user
//just a log
user match {
case Full(u) => logger.info("user " + u.emailAddress + " was found from the DirectLogin token")
case Full(u) => logger.info("user " + u.name + " was found from the DirectLogin token")
case _ => logger.info("no user was found for the DirectLogin token")
}
user

View File

@ -519,7 +519,7 @@ object OAuthHandshake extends RestHelper with Loggable {
val user = token.user
//just a log
user match {
case Full(u) => logger.info("user " + u.emailAddress + " was found from the oauth token")
case Full(u) => logger.info("user " + u.name + " was found from the oauth token")
case _ => logger.info("no user was found for the oauth token")
}
user

View File

@ -1340,7 +1340,7 @@ trait APIMethods200 {
| May require validation of email address.
|
|""",
Extraction.decompose(CreateUserJSON("someone@example.com", "my-secure-password", "James", "Brown")),
Extraction.decompose(CreateUserJSON("someone@example.com", "my-username", "my-secure-password", "James", "Brown")),
emptyObjectJson,
emptyObjectJson :: Nil,
true,
@ -1354,10 +1354,11 @@ trait APIMethods200 {
for {
postedData <- tryo {json.extract[CreateUserJSON]} ?~! ErrorMessages.InvalidJsonFormat
} yield {
if (OBPUser.find(By(OBPUser.email, postedData.email)).isEmpty) {
if (OBPUser.find(By(OBPUser.username, postedData.username)).isEmpty) {
val userCreated = OBPUser.create
.firstName(postedData.first_name)
.lastName(postedData.last_name)
.username(postedData.username)
.email(postedData.email)
.password(postedData.password)
.validated(true) // TODO Get this from Props
@ -1376,7 +1377,7 @@ trait APIMethods200 {
}
}
else {
Full(errorJsonResponse("User with the same email already exists.", 409))
Full(errorJsonResponse("User with the same username already exists.", 409))
}
}
}
@ -1667,8 +1668,8 @@ trait APIMethods200 {
"getUser",
"GET",
"/users/USER_EMAIL",
"Get User by Email Address",
"""Get the user by email address
"Get Users by Email Address",
"""Get users by email address
|
|Login is required.
|CanGetAnyUser entitlement is required,
@ -1688,14 +1689,13 @@ trait APIMethods200 {
user =>
for {
l <- user ?~ ErrorMessages.UserNotLoggedIn
//b <- tryo{Bank.all.headOption} ?~! {ErrorMessages.BankNotFound} //TODO: This is a temp workaround
canGetAnyUser <- booleanToBox(hasEntitlement("", l.userId, ApiRole.CanGetAnyUser), "CanGetAnyUser entitlement required")
// Workaround to get userEmail address directly from URI without needing to URL-encode it
u <- OBPUser.getApiUserByEmail(CurrentReq.value.uri.split("/").last) ?~! {ErrorMessages.UserNotFoundByEmail}
users <- tryo{OBPUser.getApiUsersByEmail(CurrentReq.value.uri.split("/").last)} ?~! {ErrorMessages.UserNotFoundByEmail}
}
yield {
// Format the data as V2.0.0 json
val json = JSONFactory200.createUserJSON(u)
val json = JSONFactory200.createUserJSONs(users)
successJsonResponse(Extraction.decompose(json))
}
}

View File

@ -74,11 +74,15 @@ class ResultAndLinksJSON(
case class CreateUserJSON(
email: String,
username: String,
password: String,
first_name: String,
last_name: String
)
case class CreateUserJSONs(
users : List[CreateUserJSON]
)
case class CreateMeetingJSON(
provider_id: String,
@ -482,19 +486,20 @@ object JSONFactory200{
email : String,
provider_id: String,
provider : String,
display_name : String
username : String
)
case class UserJSONs(
users: List[UserJSON]
)
def createUserJSONfromOBPUser(user : OBPUser) : UserJSON = new UserJSON(
user_id = user.user.foreign.get.userId,
email = user.email,
username = stringOrNull(user.username),
provider_id = stringOrNull(user.provider),
provider = stringOrNull(user.provider),
display_name = stringOrNull(user.displayName())
provider = stringOrNull(user.provider)
)
@ -502,9 +507,9 @@ object JSONFactory200{
new UserJSON(
user_id = user.userId,
email = user.emailAddress,
username = stringOrNull(user.name),
provider_id = user.idGivenByProvider,
provider = stringOrNull(user.provider),
display_name = stringOrNull(user.name) //TODO: Rename to displayName ?
provider = stringOrNull(user.provider)
)
}
@ -515,6 +520,10 @@ object JSONFactory200{
}
}
def createUserJSONs(users : List[User]) : UserJSONs = {
UserJSONs(users.map(createUserJSON))
}
def createUserJSONfromOBPUser(user : Box[OBPUser]) : UserJSON = {
@ -681,7 +690,6 @@ object JSONFactory200{
/** Creates v2.0.0 representation of a TransactionType
*
*
* @param transactionType An internal TransactionType instance
* @return a v2.0.0 representation of a TransactionType
@ -705,7 +713,6 @@ def createTransactionTypeJSON(transactionType : TransactionType) : TransactionTy
/** Creates v2.0.0 representation of a TransactionType
*
*
* @param tr An internal TransactionRequest instance
* @return a v2.0.0 representation of a TransactionRequest

View File

@ -31,6 +31,8 @@
*/
package code.model.dataAccess
import java.util.UUID
import code.api.{DirectLogin, OAuthHandshake}
import code.bankconnectors.KafkaMappedConnector
import code.bankconnectors.KafkaMappedConnector.KafkaInboundUser
@ -55,6 +57,18 @@ class OBPUser extends MegaProtoUser[OBPUser] with Logger {
object user extends MappedLongForeignKey(this, APIUser)
/**
* 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"))
}
/**
* The provider field for the User.
*/
@ -64,15 +78,6 @@ class OBPUser extends MegaProtoUser[OBPUser] with Logger {
override val fieldId = Some(Text("txtProvider"))
}
def displayName() = {
if(firstName.get.isEmpty) {
lastName.get
} else if(lastName.get.isEmpty) {
firstName.get
} else {
firstName.get + " " + lastName.get
}
}
def getProvider() = {
if(provider.get == null) {
@ -86,14 +91,18 @@ class OBPUser extends MegaProtoUser[OBPUser] with Logger {
def createUnsavedApiUser() : APIUser = {
APIUser.create
.name_(displayName())
.name_(username)
.email(email)
.provider_(getProvider())
.providerId(email)
.providerId(username)
}
def getApiUserByEmail(userEmail: String) : Box[APIUser] = {
APIUser.find(By(APIUser.email, userEmail))
def getApiUsersByEmail(userEmail: String) : List[APIUser] = {
APIUser.findAll(By(APIUser.email, userEmail))
}
def getApiUserByUsername(username: String) : Box[APIUser] = {
APIUser.find(By(APIUser.name_, username))
}
override def save(): Boolean = {
@ -107,8 +116,9 @@ class OBPUser extends MegaProtoUser[OBPUser] with Logger {
info("user reference is not null. Trying to update the API User")
user.obj.map{ u =>{
info("API User found ")
u.name_(displayName())
u.name_(username)
.email(email)
.providerId(username)
.save
}
}
@ -134,6 +144,8 @@ class OBPUser extends MegaProtoUser[OBPUser] with Logger {
// 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"))))
}
}
@ -150,8 +162,8 @@ import net.liftweb.util.Helpers._
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, password, provider)
override def signupFields = List(firstName, lastName, email, password)
override def fieldOrder = List(id, firstName, lastName, email, username, password, provider)
override def signupFields = List(firstName, lastName, email, username, password)
// comment this line out to require email validations
override def skipEmailValidation = true
@ -160,7 +172,7 @@ import net.liftweb.util.Helpers._
val loginXml = Templates(List("templates-hidden","_login")).map({
"form [action]" #> {S.uri} &
"#loginText * " #> {S.?("log.in")} &
"#emailAddressText * " #> {S.?("email.address")} &
"#usernameText * " #> {S.?("username")} &
"#passwordText * " #> {S.?("password")} &
"#recoverPasswordLink * " #> {
"a [href]" #> {lostPasswordPath.mkString("/", "/", "")} &
@ -180,17 +192,17 @@ import net.liftweb.util.Helpers._
*/
def getCurrentUserUsername: String = {
if (OAuthHandshake.getUser.getOrElse(None) != None )
return OAuthHandshake.getUser.get.emailAddress
return OAuthHandshake.getUser.get.name
if (DirectLogin.getUser.getOrElse(None) != None)
return DirectLogin.getUser.get.emailAddress
return DirectLogin.getUser.get.name
return ""
}
/**
* Overridden to use the hostname set in the props file
*/
override def sendPasswordReset(email: String) {
findUserByUserName(email) match {
override def sendPasswordReset(name: String) {
findUserByUsername(name) match {
case Full(user) if user.validated_? =>
user.resetUniqueId().save
val resetLink = Props.get("hostname", "ERROR")+
@ -217,10 +229,10 @@ import net.liftweb.util.Helpers._
<div id="authorizeSection">
<div id="userAccess">
<div class="account account-in-content">
{S.?("enter.email")}
{S.?("enter.username")}
<form class="forgotPassword" action={S.uri} method="post">
<div class="field username">
<label>{userNameFieldString}</label> <user:email />
<label>{userNameFieldString}</label> <user:username />
</div>
<div class="field buttons">
@ -295,8 +307,8 @@ import net.liftweb.util.Helpers._
// What if we just want to return the userId without sending username/password??
def getUserId(username: String, password: String): Box[Long] = {
findUserByUserName(username) match {
def getUserId(name: String, password: String): Box[Long] = {
findUserByUsername(name) match {
case Full(user) => {
if (user.validated_? &&
user.getProvider() == Props.get("hostname","") &&
@ -307,7 +319,7 @@ import net.liftweb.util.Helpers._
else {
Props.get("connector").openOrThrowException("no connector set") match {
case "kafka" =>
for { kafkaUser <- getUserFromKafka(username, password)
for { kafkaUser <- getUserFromKafka(name, password)
kafkaUserId <- tryo{kafkaUser.id} } yield kafkaUserId.toLong
case _ => Full(0)
}
@ -317,9 +329,9 @@ import net.liftweb.util.Helpers._
}
}
def getUserFromKafka(username: String, password: String):Box[OBPUser] = {
KafkaMappedConnector.getUser(username, password) match {
case Full(KafkaInboundUser(extEmail, extPassword, extDisplayName)) => {
def getUserFromKafka(name: String, password: String):Box[OBPUser] = {
KafkaMappedConnector.getUser(name, password) match {
case Full(KafkaInboundUser(extEmail, extPassword, extUsername)) => {
info("external user authenticated. login redir: " + loginRedirect.get)
val redir = loginRedirect.get match {
case Full(url) =>
@ -329,10 +341,9 @@ import net.liftweb.util.Helpers._
homePage
}
val dummyPassword = "nothingreallyjustdummypass"
val extProvider = Props.get("connector").openOrThrowException("no connector set")
val user = findUserByUserName(username) match {
val user = findUserByUsername(name) match {
// Check if the external user is already created locally
case Full(user) if user.validated_? &&
user.provider == extProvider => {
@ -347,10 +358,11 @@ import net.liftweb.util.Helpers._
// assuming that user's email is always validated
info("external user "+ extEmail +" does not exist locally, creating one")
val newUser = OBPUser.create
.firstName(extDisplayName)
.firstName(extUsername)
.email(extEmail)
.username(extUsername)
// No need to store password, so store dummy string instead
.password(dummyPassword)
.password(UUID.randomUUID().toString)
.provider(extProvider)
.validated(true)
// Save the user in order to be able to log in
@ -371,7 +383,7 @@ import net.liftweb.util.Helpers._
override def login = {
if (S.post_?) {
S.param("username").
flatMap(username => findUserByUserName(username)) match {
flatMap(name => findUserByUsername(name)) match {
case Full(user) if user.validated_? &&
// Check if user came from localhost
user.getProvider() == Props.get("hostname","") &&
@ -422,16 +434,16 @@ import net.liftweb.util.Helpers._
}
bind("user", loginXhtml,
"email" -> (FocusOnLoad(<input type="text" name="username"/>)),
"username" -> (FocusOnLoad(<input type="text" name="username"/>)),
"password" -> (<input type="password" name="password"/>),
"submit" -> loginSubmitButton(S.?("log.in")))
}
def externalUserHelper(username: String, password: String): Box[OBPUser] = {
def externalUserHelper(name: String, password: String): Box[OBPUser] = {
if (Props.get("connector").openOrThrowException("no connector set") == "kafka") {
for {
user <- getUserFromKafka(username, password)
u <- APIUser.find(By(APIUser.email, user.email))
user <- getUserFromKafka(name, password)
u <- APIUser.find(By(APIUser.name_, user.username))
v <- tryo {KafkaMappedConnector.updateUserAccountViews(u)}
} yield {
user
@ -439,6 +451,9 @@ import net.liftweb.util.Helpers._
} else Full(OBPUser)
}
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,

View File

@ -18,7 +18,7 @@ trait CreateOBPUsers {
}
}
val existingObpUser = OBPUser.find(By(OBPUser.email, u.email))
val existingObpUser = OBPUser.find(By(OBPUser.username, u.user_name))
if(existingObpUser.isDefined) {
logger.warn(s"Existing OBPUser with email ${u.email} detected in data import where no APIUser was found")
@ -26,7 +26,8 @@ trait CreateOBPUsers {
} else {
val obpUser = OBPUser.create
.email(u.email)
.lastName(u.display_name)
.lastName(u.user_name)
.username(u.user_name)
.password(u.password)
.validated(true)

View File

@ -47,7 +47,7 @@ trait OBPDataImport extends Loggable {
type MetadataType <: OtherBankAccountMetadata
type ViewType <: View
type TransactionType <: TransactionUUID
type AccountOwnerEmail = String
type AccountOwnerUsername = String
type BranchType <: Branch
type AtmType <: Atm
type ProductType <: Product
@ -135,17 +135,17 @@ trait OBPDataImport extends Loggable {
protected def createSaveableUser(u : SandboxUserImport) : Box[Saveable[APIUser]]
protected def createUsers(toImport : List[SandboxUserImport]) : Box[List[Saveable[APIUser]]] = {
val existingApiUsers = toImport.flatMap(u => APIUser.find(By(APIUser.email, u.email)))
val allEmails = toImport.map(_.email)
val duplicateEmails = allEmails diff allEmails.distinct
val existingApiUsers = toImport.flatMap(u => APIUser.find(By(APIUser.name_, u.user_name)))
val allUsernames = toImport.map(_.user_name)
val duplicateUsernames = allUsernames diff allUsernames.distinct
def usersExist(existingEmails : List[String]) =
Failure(s"User(s) with email(s) $existingEmails already exist (and may be different (e.g. different display_name)")
if(!existingApiUsers.isEmpty) {
usersExist(existingApiUsers.map(_.email.get))
} else if(!duplicateEmails.isEmpty) {
Failure(s"Users must have unique emails: Duplicates found: $duplicateEmails")
usersExist(existingApiUsers.map(_.name))
} else if(!duplicateUsernames.isEmpty) {
Failure(s"Users must have unique usernames: Duplicates found: $duplicateUsernames")
}else {
val apiUsers = toImport.map(createSaveableUser(_))
@ -159,8 +159,8 @@ trait OBPDataImport extends Loggable {
*
* TODO: this only works after createdUsers have been saved (and thus an APIUser has been created
*/
protected def setAccountOwner(owner : AccountOwnerEmail, account: BankAccount, createdUsers: List[APIUser]): AnyVal = {
val apiUserOwner = createdUsers.find(user => owner == user.emailAddress)
protected def setAccountOwner(owner : AccountOwnerUsername, account: BankAccount, createdUsers: List[APIUser]): AnyVal = {
val apiUserOwner = createdUsers.find(user => owner == user.name)
apiUserOwner match {
case Some(o) => {
@ -168,7 +168,7 @@ trait OBPDataImport extends Loggable {
}
case None => {
//This shouldn't happen as OBPUser should generate the APIUsers when saved
logger.error(s"api user(s) with email $owner not found.")
logger.error(s"api user $owner not found.")
logger.error("Data import completed with errors.")
}
}
@ -286,9 +286,9 @@ trait OBPDataImport extends Loggable {
final protected def createCrmEvents(data : SandboxDataImport) = {
createSaveableCrmEvents(data.crm_events)
}
@ -297,8 +297,8 @@ trait OBPDataImport extends Loggable {
for {
ownersNonEmpty <- Helper.booleanToBox(acc.owners.nonEmpty) ?~
s"Accounts must have at least one owner. Violation: (bank id ${acc.bank}, account id ${acc.id})"
ownersDefinedInDataImport <- Helper.booleanToBox(acc.owners.forall(ownerEmail => data.users.exists(u => u.email == ownerEmail))) ?~ {
val violations = acc.owners.filter(ownerEmail => !data.users.exists(u => u.email == ownerEmail))
ownersDefinedInDataImport <- Helper.booleanToBox(acc.owners.forall(ownerUsername => data.users.exists(u => u.user_name == ownerUsername))) ?~ {
val violations = acc.owners.filter(ownerUsername => !data.users.exists(u => u.user_name == ownerUsername))
s"Accounts must have owner(s) defined in data import. Violation: ${violations.mkString(",")}"
}
accId = AccountId(acc.id)
@ -312,7 +312,7 @@ trait OBPDataImport extends Loggable {
} yield acc
}
final protected def createAccountsAndViews(data : SandboxDataImport, banks : List[BankType]) : Box[List[(Saveable[AccountType], List[Saveable[ViewType]], List[AccountOwnerEmail])]] = {
final protected def createAccountsAndViews(data : SandboxDataImport, banks : List[BankType]) : Box[List[(Saveable[AccountType], List[Saveable[ViewType]], List[AccountOwnerUsername])]] = {
val banksNotSpecifiedInImport = data.accounts.flatMap(acc => {
if(data.banks.exists(b => b.id == acc.bank)) None
@ -356,7 +356,7 @@ trait OBPDataImport extends Loggable {
}
final protected def createSaveableAccountResults(accs : List[SandboxAccountImport], banks : List[BankType])
: Box[List[(Saveable[AccountType], List[Saveable[ViewType]], List[AccountOwnerEmail])]] = {
: Box[List[(Saveable[AccountType], List[Saveable[ViewType]], List[AccountOwnerUsername])]] = {
logger.info("Hello from createSaveableAccountResults")
@ -518,18 +518,18 @@ trait OBPDataImport extends Loggable {
logger.info(s"importData is saving ${accountResults.size} accountResults (accounts, views and permissions)..")
accountResults.foreach {
case (account, views, accOwnerEmails) =>
case (account, views, accOwnerUsernames) =>
account.save()
views.foreach(_.save())
views.map(_.value).filterNot(_.isPublic).foreach(v => {
//grant the owner access to non-public views
//this should always find the owners as that gets verified at an earlier stage, but it's not perfect this way
val accOwners = users.map(_.value).filter(u => accOwnerEmails.exists(email => u.emailAddress == email))
val accOwners = users.map(_.value).filter(u => accOwnerUsernames.exists(name => u.name == name))
accOwners.foreach(Views.views.vend.addPermission(v.uid, _))
})
accOwnerEmails.foreach(setAccountOwner(_, account.value, users.map(_.value)))
accOwnerUsernames.foreach(setAccountOwner(_, account.value, users.map(_.value)))
}
logger.info(s"importData is saving ${transactions.size} transactions (and loading them again)")
transactions.foreach { t =>
@ -594,7 +594,7 @@ case class SandboxLocationImport(
case class SandboxUserImport(
email : String,
password : String,
display_name : String)
user_name : String)
case class SandboxAccountImport(
id : String,

View File

@ -32,14 +32,12 @@ Berlin 13359, Germany
package code.snippet
import code.model.dataAccess.OBPUser
import net.liftweb.common.Loggable
import scala.xml.NodeSeq
import code.model.dataAccess.{Admin, OBPUser}
import net.liftweb.http.{S, SHtml}
import net.liftweb.util.Helpers._
import net.liftweb.util.{Props, CssSel}
import net.liftweb.http.S
import code.model.dataAccess.Admin
import net.liftweb.http.SHtml
import net.liftweb.util.{CssSel, Props}
import scala.xml.NodeSeq
class Login {
@ -50,7 +48,7 @@ class Login {
".logout [href]" #> {
OBPUser.logoutPath.foldLeft("")(_ + "/" + _)
} &
".username *" #> OBPUser.currentUser.get.email.get
".username *" #> OBPUser.currentUser.get.username.get
}
}

View File

@ -462,7 +462,7 @@ input.submit {
#main-partners a {
vertical-align: top;
display: inline-block;
*display: inline;
/* *display: inline; */
/* zoom: 1; */
margin: 30px 30px 30px 30px;
}

View File

@ -3,7 +3,7 @@
<div class="account account-in-content">
<div class="login-error"><span class="lift:Msg?id=login&errorClass=error"/></div>
<!-- LOGGED OUT -->
Please login with your username or e-mail address.
Please login with your username.
<div class="lift:embed?what=_login_form"></div>
</div>
</div>

View File

@ -7,7 +7,7 @@
<div class="field username">
<input class="username" type="email" placeholder="Username" name="username" tabindex=1 autofocus />
<input class="username" type="text" placeholder="Username" name="username" tabindex=1 autofocus />
</div>
<div class="field password">
<input class="password" type="password" placeholder="Password" name="password" tabindex=2 />

View File

@ -103,7 +103,7 @@ Berlin 13359, Germany
</div>
<div class="lift:Login.loggedIn">
<div class="profile-info">
<span class="username">username@domain.com</span>&nbsp;<a href="" class="logout">Logout</a>
<span class="username">username</span>&nbsp;<a href="" class="logout">Logout</a>
</div>
</div>
</li>

View File

@ -16,12 +16,14 @@ class directloginTest extends ServerSetup with BeforeAndAfter {
val KEY = randomString(40).toLowerCase
val SECRET = randomString(40).toLowerCase
val EMAIL = randomString(10).toLowerCase + "@example.com"
val USERNAME = randomString(10).toLowerCase
val PASSWORD = randomString(20)
before {
if (OBPUser.find(By(OBPUser.email, EMAIL)).isEmpty)
if (OBPUser.find(By(OBPUser.username, USERNAME)).isEmpty)
OBPUser.create.
email(EMAIL).
username(USERNAME).
password(PASSWORD).
validated(true).
firstName(randomString(10)).
@ -39,14 +41,14 @@ class directloginTest extends ServerSetup with BeforeAndAfter {
val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*")
val invalidUsernamePasswordHeader = ("Authorization", ("DirectLogin username=\"does-not-exist@example.com\", " +
val invalidUsernamePasswordHeader = ("Authorization", ("DirectLogin username=\"does-not-exist\", " +
"password=\"no-good-password\", consumer_key=%s").format(KEY))
val invalidConsumerKeyHeader = ("Authorization", ("DirectLogin username=%s, " +
"password=%s, consumer_key=%s").format(EMAIL, PASSWORD, "invalid"))
"password=%s, consumer_key=%s").format(USERNAME, PASSWORD, "invalid"))
val validHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s".
format(EMAIL, PASSWORD, KEY))
format(USERNAME, PASSWORD, KEY))
val invalidUsernamePasswordHeaders = List(accessControlOriginHeader, invalidUsernamePasswordHeader)

View File

@ -70,6 +70,7 @@ class OAuthTest extends ServerSetup {
lazy val user1 =
OBPUser.create.
email(randomString(3)+"@example.com").
username(randomString(9)).
password(user1Password).
validated(true).
firstName(randomString(10)).
@ -113,7 +114,7 @@ class OAuthTest extends ServerSetup {
def getVerifier(loginPage: String, userName: String, password: String) : Box[String] = {
tryo{
go.to(loginPage)
emailField("username").value = userName
textField("username").value = userName
val pwField = NameQuery("password").webElement
pwField.clear()
pwField.sendKeys(password)
@ -198,7 +199,7 @@ class OAuthTest extends ServerSetup {
val reply = getRequestToken(consumer, selfCallback)
val requestToken = extractToken(reply.body)
When("the browser is launched to login")
val verifier = getVerifier(requestToken.value, user1.email.get, user1Password)
val verifier = getVerifier(requestToken.value, user1.username.get, user1Password)
Then("we should get a verifier")
verifier.get.nonEmpty should equal (true)
}
@ -207,21 +208,21 @@ class OAuthTest extends ServerSetup {
val reply = getRequestToken(consumer, oob)
val requestToken = extractToken(reply.body)
When("the browser is launched to login")
val verifier = getVerifier(requestToken.value, user1.email.get, user1Password)
val verifier = getVerifier(requestToken.value, user1.username.get, user1Password)
Then("we should get a verifier")
verifier.isEmpty should equal (false)
}
scenario("the user cannot login because there is no token", Verifier, Oauth){
Given("there will be no token")
When("the browser is launched to login")
val verifier = getVerifier(user1.email.get, user1Password)
val verifier = getVerifier(user1.username.get, user1Password)
Then("we should not get a verifier")
verifier.isEmpty should equal (true)
}
scenario("the user cannot login because the token does not exist", Verifier, Oauth){
Given("we will use a random request token")
When("the browser is launched to login")
val verifier = getVerifier(randomString(4), user1.email.get, user1Password)
val verifier = getVerifier(randomString(4), user1.username.get, user1Password)
Then("we should not get a verifier")
verifier.isEmpty should equal (true)
}
@ -231,7 +232,7 @@ class OAuthTest extends ServerSetup {
Given("we will first get a request token and a verifier")
val reply = getRequestToken(consumer, oob)
val requestToken = extractToken(reply.body)
val verifier = getVerifier(requestToken.value, user1.email.get, user1Password)
val verifier = getVerifier(requestToken.value, user1.username.get, user1Password)
When("when we ask for an access token")
val accessToken = getAccessToken(consumer, requestToken, verifier.get)
Then("we should get an access token")
@ -241,7 +242,7 @@ class OAuthTest extends ServerSetup {
Given("we will first get a request token and a verifier")
val reply = getRequestToken(consumer, selfCallback)
val requestToken = extractToken(reply.body)
val verifier = getVerifier(requestToken.value, user1.email.get, user1Password)
val verifier = getVerifier(requestToken.value, user1.username.get, user1Password)
When("when we ask for an access token")
val accessToken = getAccessToken(consumer, requestToken, verifier.get)
Then("we should get an access token")
@ -260,7 +261,7 @@ class OAuthTest extends ServerSetup {
Given("we will first get request token and a verifier")
val reply = getRequestToken(consumer, selfCallback)
val requestToken = extractToken(reply.body)
val verifier = getVerifier(requestToken.value, user1.email.get, user1Password)
val verifier = getVerifier(requestToken.value, user1.username.get, user1Password)
When("when we ask for an access token with a request token")
val randomRequestToken = Token(randomString(5), randomString(5))
val accessTokenReply = getAccessToken(consumer, randomRequestToken, verifier.get)

View File

@ -20,6 +20,7 @@ class CreateUserTest extends V200ServerSetup with BeforeAndAfter {
val FIRSTNAME = randomString(8).toLowerCase
val LASTNAME = randomString(16).toLowerCase
val USERNAME = randomString(10).toLowerCase
val EMAIL = randomString(10).toLowerCase + "@example.com"
val PASSWORD = randomString(20)
@ -43,7 +44,7 @@ class CreateUserTest extends V200ServerSetup with BeforeAndAfter {
val accessControlOriginHeader = ("Access-Control-Allow-Origin", "*")
val validHeader = ("Authorization", "DirectLogin username=%s, password=%s, consumer_key=%s".
format(EMAIL, PASSWORD, KEY))
format(USERNAME, PASSWORD, KEY))
val validHeaders = List(accessControlOriginHeader, validHeader)
private def getAPIResponse(req : Req) : OAuthResponse = {
@ -72,9 +73,10 @@ class CreateUserTest extends V200ServerSetup with BeforeAndAfter {
feature("we can create an user and login as newly created user using both directLogin and OAuth") {
scenario("we create an user with email, first name, last name and password", CreateUser) {
scenario("we create an user with email, first name, last name , username and password", CreateUser) {
When("we create a new user")
val params = Map("email" -> EMAIL,
"username" -> USERNAME,
"password" -> PASSWORD,
"first_name" -> FIRSTNAME,
"last_name" -> LASTNAME)
@ -114,6 +116,7 @@ class CreateUserTest extends V200ServerSetup with BeforeAndAfter {
scenario("we try to create a same user again", CreateUser) {
When("we create a same user")
val params = Map("email" -> EMAIL,
"username" -> USERNAME,
"password" -> PASSWORD,
"first_name" -> FIRSTNAME,
"last_name" -> LASTNAME)

View File

@ -257,15 +257,15 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
}
def verifyUserCreated(user : SandboxUserImport) = {
val foundUserBox = Users.users.vend.getUserByProviderId(defaultProvider, user.email)
val foundUserBox = Users.users.vend.getUserByProviderId(defaultProvider, user.user_name)
foundUserBox.isDefined should equal(true)
val foundUser = foundUserBox.get
foundUser.provider should equal(defaultProvider)
foundUser.idGivenByProvider should equal(user.email)
foundUser.idGivenByProvider should equal(user.user_name)
foundUser.emailAddress should equal(user.email)
foundUser.name should equal(user.display_name)
foundUser.name should equal(user.user_name)
}
def verifyAccountCreated(account : SandboxAccountImport) = {
@ -285,7 +285,7 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
foundAccount.balance.toString should equal(account.balance.amount)
foundAccount.currency should equal(account.balance.currency)
foundAccount.owners.map(_.emailAddress) should equal(account.owners.toSet)
foundAccount.owners.map(_.name) should equal(account.owners.toSet)
if(account.generate_public_view) {
foundAccount.publicViews.size should equal(1)
@ -293,7 +293,7 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
foundAccount.publicViews.size should equal(0)
}
val owner = Users.users.vend.getUserByProviderId(defaultProvider, foundAccount.owners.toList.head.emailAddress).get
val owner = Users.users.vend.getUserByProviderId(defaultProvider, foundAccount.owners.toList.head.name).get
//there should be an owner view
val views = foundAccount.views(owner).get
@ -457,21 +457,21 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
val standardProducts = product1AtBank1 :: product2AtBank1 :: Nil
val user1 = SandboxUserImport(email = "user1@example.com", password = "qwerty", display_name = "User 1")
val user2 = SandboxUserImport(email = "user2@example.com", password = "qwerty", display_name = "User 2")
val user1 = SandboxUserImport(email = "user1@example.com", password = "qwerty", user_name = "User 1")
val user2 = SandboxUserImport(email = "user2@example.com", password = "qwerty", user_name = "User 2")
val standardUsers = user1 :: user2 :: Nil
val account1AtBank1 = SandboxAccountImport(id = "account1", bank = "bank1", label = "Account 1 at Bank 1",
number = "1", `type` = "savings", IBAN = "1234567890", generate_public_view = true, owners = List(user1.email),
number = "1", `type` = "savings", IBAN = "1234567890", generate_public_view = true, owners = List(user1.user_name),
balance = SandboxBalanceImport(currency = "EUR", amount = "1000.00"), generate_accountants_view = true, generate_auditors_view = true)
val account2AtBank1 = SandboxAccountImport(id = "account2", bank = "bank1", label = "Account 2 at Bank 1",
number = "2", `type` = "current", IBAN = "91234567890", generate_public_view = false, owners = List(user2.email),
number = "2", `type` = "current", IBAN = "91234567890", generate_public_view = false, owners = List(user2.user_name),
balance = SandboxBalanceImport(currency = "EUR", amount = "2000.00"), generate_accountants_view = true, generate_auditors_view = true)
val account1AtBank2 = SandboxAccountImport(id = "account1", bank = "bank2", label = "Account 1 at Bank 2",
number = "22", `type` = "savings", IBAN = "21234567890", generate_public_view = false, owners = List(user1.email, user2.email),
number = "22", `type` = "savings", IBAN = "21234567890", generate_public_view = false, owners = List(user1.user_name, user2.user_name),
balance = SandboxBalanceImport(currency = "EUR", amount = "1500.00"), generate_accountants_view = true, generate_auditors_view = true)
val standardAccounts = account1AtBank1 :: account2AtBank1 :: account1AtBank2 :: Nil
@ -744,7 +744,7 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
getResponse(userWithInvalidEmail).code should equal(FAILED)
//there should still be no user
Users.users.vend.getUserByProviderId(defaultProvider, invalidEmail) should equal(Empty)
Users.users.vend.getUserByProviderId(defaultProvider, user1.user_name) should equal(Empty)
val validEmail = "test@example.com"
val userWithValidEmail = addEmailField(userWithoutEmail, validEmail)
@ -752,15 +752,15 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
getResponse(userWithValidEmail).code should equal(SUCCESS)
//a user should now have been created
val createdUser = Users.users.vend.getUserByProviderId(defaultProvider, validEmail)
val createdUser = Users.users.vend.getUserByProviderId(defaultProvider, user1.user_name)
createdUser.isDefined should equal(true)
createdUser.get.provider should equal(defaultProvider)
createdUser.get.idGivenByProvider should equal(validEmail)
createdUser.get.emailAddress should equal(validEmail)
createdUser.get.idGivenByProvider should equal(user1.user_name)
createdUser.get.name should equal(user1.user_name)
}
it should "not allow multiple users with the same email" in {
it should "not allow multiple users with the same username" in {
def getResponse(userJsons : List[JValue]) = {
val json = createImportJson(Nil, userJsons, Nil, Nil, Nil, Nil, Nil, Nil)
@ -768,43 +768,40 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
}
//emails of the user we will eventually create to show multiple users with different ids are possible
val secondUserEmail = "user-two@example.com"
val secondUserName = "user-two"
val user1Json = Extraction.decompose(user1)
val differentDisplayName = "Jessica Bloggs"
differentDisplayName should not equal(user1.display_name)
val userWithSameEmailAsUser1 = user1Json.replace("display_name", differentDisplayName)
val differentUsername = "user-one"
differentUsername should not equal(user1.user_name)
val userWithSameUsernameAsUser1 = user1Json
//neither of the users should exist initially
Users.users.vend.getUserByProviderId(defaultProvider, user1.email) should equal(Empty)
Users.users.vend.getUserByProviderId(defaultProvider, secondUserEmail) should equal(Empty)
Users.users.vend.getUserByProviderId(defaultProvider, user1.user_name) should equal(Empty)
Users.users.vend.getUserByProviderId(defaultProvider, secondUserName) should equal(Empty)
getResponse(List(user1Json, userWithSameEmailAsUser1)).code should equal(FAILED)
getResponse(List(user1Json, userWithSameUsernameAsUser1)).code should equal(FAILED)
//no user with firstUserId should be created
Users.users.vend.getUserByProviderId(defaultProvider, user1.email) should equal(Empty)
Users.users.vend.getUserByProviderId(defaultProvider, user1.user_name) should equal(Empty)
//when we only alter the id (display name stays the same), it should work
val userWithEmail2 = userWithSameEmailAsUser1.replace("email", secondUserEmail)
val userWithUsername2 = userWithSameUsernameAsUser1.replace("user_name", secondUserName)
getResponse(List(user1Json, userWithEmail2)).code should equal(SUCCESS)
getResponse(List(user1Json, userWithUsername2)).code should equal(SUCCESS)
//and both users should be created
val firstUser = Users.users.vend.getUserByProviderId(defaultProvider, user1.email)
val secondUser = Users.users.vend.getUserByProviderId(defaultProvider, secondUserEmail)
val firstUser = Users.users.vend.getUserByProviderId(defaultProvider, user1.user_name)
val secondUser = Users.users.vend.getUserByProviderId(defaultProvider, secondUserName)
firstUser.isDefined should equal(true)
secondUser.isDefined should equal(true)
firstUser.get.idGivenByProvider should equal(user1.email)
secondUser.get.idGivenByProvider should equal(secondUserEmail)
firstUser.get.idGivenByProvider should equal(user1.user_name)
secondUser.get.idGivenByProvider should equal(secondUserName)
firstUser.get.emailAddress should equal(user1.email)
secondUser.get.emailAddress should equal(secondUserEmail)
firstUser.get.name should equal(user1.display_name)
secondUser.get.name should equal(differentDisplayName)
firstUser.get.name should equal(user1.user_name)
secondUser.get.name should equal(secondUserName)
}
it should "fail if a specified user already exists" in {
@ -824,7 +821,7 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
getResponse(List(user1Json, Extraction.decompose(otherUser))).code should equal(FAILED)
//and the other user should not have been created
Users.users.vend.getUserByProviderId(defaultProvider, otherUser.email)
Users.users.vend.getUserByProviderId(defaultProvider, otherUser.user_name)
}
it should "fail if a user's password is missing or empty" in {
@ -838,16 +835,16 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
val userWithoutPassword = removeField(goodUser, "password")
getResponse(List(userWithoutPassword)).code should equal(FAILED)
//no user should be created
Users.users.vend.getUserByProviderId(defaultProvider, user1.email).isDefined should equal(false)
Users.users.vend.getUserByProviderId(defaultProvider, user1.user_name).isDefined should equal(false)
val userWithBlankPassword = replaceField(goodUser, "password", "")
getResponse(List(userWithBlankPassword)).code should equal(FAILED)
//no user should be created
Users.users.vend.getUserByProviderId(defaultProvider, user1.email).isDefined should equal(false)
Users.users.vend.getUserByProviderId(defaultProvider, user1.user_name).isDefined should equal(false)
//check that a normal password is okay
getResponse(List(goodUser)).code should equal(SUCCESS)
Users.users.vend.getUserByProviderId(defaultProvider, user1.email).isDefined should equal(true)
Users.users.vend.getUserByProviderId(defaultProvider, user1.user_name).isDefined should equal(true)
}
it should "set user passwords properly" in {
@ -860,7 +857,7 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
//TODO: we shouldn't reference OBPUser here as it is an implementation, but for now there
//is no way to check User (the trait) passwords
val createdOBPUserBox = OBPUser.find(By(OBPUser.email, user1.email))
val createdOBPUserBox = OBPUser.find(By(OBPUser.username, user1.user_name))
createdOBPUserBox.isDefined should equal(true)
val createdOBPUser = createdOBPUserBox.get
@ -1006,7 +1003,7 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Shoul
Connector.connector.vend.getBankAccount(BankId(accountWithInvalidOwner.bank), AccountId(accountWithInvalidOwner.id)).isDefined should equal(false)
//a mix of valid an invalid owners should also not work
val accountWithSomeValidSomeInvalidOwners = accountWithInvalidOwner.copy(owners = List(accountWithInvalidOwner.owners + user1.email))
val accountWithSomeValidSomeInvalidOwners = accountWithInvalidOwner.copy(owners = List(accountWithInvalidOwner.owners + user1.user_name))
getResponse(List(Extraction.decompose(accountWithSomeValidSomeInvalidOwners))).code should equal(FAILED)
//it should not have been created