Added an API call to grant access a user to a list of views

and some tests for that API call.
This commit is contained in:
Ayoub BENALI 2013-06-11 09:34:28 +02:00
parent 087ceb0034
commit bf356c868b
5 changed files with 188 additions and 5 deletions

View File

@ -247,6 +247,11 @@ case class LocationPlainJSON(
case class TransactionNarrativeJSON(
narrative : String
)
case class ViewIdsJson(
views : List[String]
)
object JSONFactory{
def stringOrNull(text : String) =
if(text.isEmpty)

View File

@ -230,7 +230,7 @@ object OBPAPI1_2 extends OBPRestHelper with Loggable {
account <- BankAccount(bankId, accountId)
u <- user ?~ "user not found"
permissions <- account permissions u
userPermission <- Box(permissions.find(p => { p.user.id_ == userId})) ?~ {userId +" not found" }
userPermission <- Box(permissions.find(p => { p.user.id_ == userId})) ?~ {"None permission found for user "+userId}
} yield {
val views = JSONFactory.createViewsJSON(userPermission.views)
successJsonResponse(Extraction.decompose(views))
@ -239,7 +239,23 @@ object OBPAPI1_2 extends OBPRestHelper with Loggable {
})
oauthServe(apiPrefix{
//add access for specific user
//add access for specific user to a list of views
case "banks" :: bankId :: "accounts" :: accountId :: "users" :: userId :: "views" :: Nil JsonPost json -> _ => {
user =>
for {
account <- BankAccount(bankId, accountId)
u <- user ?~ "user not found"
viewIds <- tryo{json.extract[ViewIdsJson]} ?~ "wrong format JSON"
addedViews <- account addPermissions(u, viewIds.views, userId)
} yield {
val viewJson = JSONFactory.createViewsJSON(addedViews)
successJsonResponse(Extraction.decompose(viewJson), 201)
}
}
})
oauthServe(apiPrefix{
//add access for specific user to a specific view
case "banks" :: bankId :: "accounts" :: accountId :: "users" :: userId :: "views" :: viewId :: Nil JsonPost json => {
user =>
for {
@ -268,8 +284,9 @@ object OBPAPI1_2 extends OBPRestHelper with Loggable {
}
})
oauthServe(apiPrefix{
//delete access for specific user to all the views
//delete access for specific user to all the views
case "banks" :: bankId :: "accounts" :: accountId :: "users" :: userId :: Nil JsonDelete json => {
user =>
for {

View File

@ -195,6 +195,42 @@ class BankAccount(
Failure("user : " + user.emailAddress + "don't have access to owner view on account " + id, Empty, Empty)
}
/**
* @param a user that want to grant an other user access to a list views
* @param the list of views ids that we want to grant access
* @param the id of the other user that we want grant access
* @return a the list of the granted views if everything is okay, a Failure otherwise
*/
def addPermissions(user : User, viewIds : List[String], otherUserId : String) : Box[List[View]] = {
//we try to get all the views that correspond to that list of view ids
lazy val viewBoxes = viewIds.map(View.fromUrl)
//we see if the the is Failures
lazy val failureList = viewBoxes.collect(v => {
v match {
case x : Failure => x
}
})
lazy val viewsFormIds : Box[List[View]] =
//if no failures then we return the Full views
if(failureList.size == 0)
Full(viewBoxes.flatten)
else
//we return just the first failure
failureList.head
//check if the user have access to the owner view in this the account
if(authorizedAccess(Owner,Full(user)))
for{
otherUser <- User.findById(otherUserId) //check if the userId corresponds to a user
views <- viewsFormIds
grantedViews <- LocalStorage.addPermissions(id, views, otherUser) ?~ "could not save the privilege"
} yield views
else
Failure("user : " + user.emailAddress + "don't have access to owner view on account " + id, Empty, Empty)
}
/**
* @param a user that want to revoke an other user access to a view
* @param the id of the view that we want to revoke access
@ -224,7 +260,7 @@ class BankAccount(
if(authorizedAccess(Owner,Full(user)))
for{
otherUser <- User.findById(otherUserId) //check if the userId corresponds to a user
isRevoked <- LocalStorage.revokeAllPermission(id, otherUser) ?~ "could not revoke the privilege"
isRevoked <- LocalStorage.revokeAllPermission(id, otherUser) ?~ "could not revoke the privileges"
} yield isRevoked
else
Failure("user : " + user.emailAddress + " don't have access to owner view on account " + id, Empty, Empty)

View File

@ -113,7 +113,6 @@ class MongoDBLocalStorage extends LocalStorage {
private val availableViews = List(Team, Board, Authorities, Public, OurNetwork, Owner, Management)
private def createTransaction(env: OBPEnvelope, theAccount: Account): Transaction = {
import net.liftweb.json.JsonDSL._
val transaction: OBPTransaction = env.obp_transaction.get
@ -584,6 +583,7 @@ class MongoDBLocalStorage extends LocalStorage {
case _ => Failure("Bank account id " + accountID + " not found.")
}
}
def permissions(account : BankAccount) : Box[List[Permission]] = {
HostedAccount.find(By(HostedAccount.accountID,account.id)) match {
@ -632,6 +632,30 @@ class MongoDBLocalStorage extends LocalStorage {
}
}
}
def addPermissions(bankAccountId : String, views : List[View], user : User) : Box[Boolean] ={
user match {
case u : OBPUser => {
for{
bankAccount <- HostedAccount.find(By(HostedAccount.accountID, bankAccountId))
} yield {
val privilege =
Privilege.create.
user(u.id).
account(bankAccount)
views.map(v => {
setPrivilegeFromView(privilege, v, true)
})
privilege.save
}
}
case u: User => {
logger.error("OBPUser instance not found, could not grant access ")
Empty
}
}
}
def revokePermission(bankAccountId : String, view : View, user : User) : Box[Boolean] = {
user match {
case user:OBPUser =>
@ -653,6 +677,7 @@ class MongoDBLocalStorage extends LocalStorage {
}
}
}
def revokeAllPermission(bankAccountId : String, user : User) : Box[Boolean] = {
user match {
case user:OBPUser =>
@ -676,6 +701,7 @@ class MongoDBLocalStorage extends LocalStorage {
}
}
}
private def setPrivilegeFromView(privilege : Privilege, view : View, value : Boolean ) = {
view match {
case OurNetwork => privilege.ourNetworkPermission(value)

View File

@ -153,6 +153,7 @@ class API1_2Test extends ServerSetup{
object GetPermissions extends Tag("getPermissions")
object GetPermission extends Tag("getPermission")
object PostPermission extends Tag("postPermission")
object PostPermissions extends Tag("postPermissions")
object DeletePermission extends Tag("deletePermission")
object DeletePermissions extends Tag("deletePermissions")
object GetOtherBankAccounts extends Tag("getOtherBankAccounts")
@ -267,6 +268,14 @@ class API1_2Test extends ServerSetup{
transactionsJson(randomPosition)
}
def randomViewsIdsToGrant(bankId : String, accountId : String) : List[String]= {
//get the view ids of the available views on the bank accounts
val viewsIds = getAccountViews(bankId, accountId).body.extract[ViewsJSON].views.map(_.id)
//choose randomly some view ids to grant
val (viewsIdsToGrant, _) = viewsIds.splitAt(nextInt(viewsIds.size) + 1)
viewsIdsToGrant
}
def getAPIInfo : h.HttpPackage[APIResponse] = {
val request = v1_2Request
makeGetRequest(request)
@ -367,6 +376,18 @@ class API1_2Test extends ServerSetup{
makePostRequest(request)
}
def grantUserAccessToViews(bankId : String, accountId : String, userId : String, viewIds : List[String]) : h.HttpPackage[APIResponse]= {
val request = (v1_2Request / "banks" / bankId / "accounts" / accountId / "users"/ userId / "views").POST.<@(consumer,token)
val viewsJson = ViewIdsJson(viewIds)
makePostRequest(request, write(viewsJson))
}
def grantUserAccessToViewsWithWrongUser(bankId : String, accountId : String, userId : String, viewIds : List[String]) : h.HttpPackage[APIResponse]= {
val request = (v1_2Request / "banks" / bankId / "accounts" / accountId / "users"/ userId / "views").POST.<@(consumer,token3)
val viewsJson = ViewIdsJson(viewIds)
makePostRequest(request, write(viewsJson))
}
def revokeUserAccessToView(bankId : String, accountId : String, userId : String, viewId : String) : h.HttpPackage[APIResponse]= {
val request = (v1_2Request / "banks" / bankId / "accounts" / accountId / "users"/ userId / "views" / viewId).DELETE.<@(consumer,token)
makeDeleteRequest(request)
@ -1533,6 +1554,83 @@ class API1_2Test extends ServerSetup{
}
}
feature("Grant a user access to a list of views on a bank account"){
scenario("we will grant a user access to a list of views on an bank account", API1_2, PostPermissions) {
Given("We will use an access token")
val bankId = randomBank
val bankAccount : AccountJSON = randomPrivateAccount(bankId)
val userId = urlEncode(user3.email)
val viewsIdsToGrant = randomViewsIdsToGrant(bankId, bankAccount.id)
When("the request is sent")
val reply = grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant)
Then("we should get a 201 ok code")
reply.code should equal (201)
val viewsInfo = reply.body.extract[ViewsJSON]
And("some fields should not be empty")
viewsInfo.views.foreach(v => v.id.nonEmpty should equal (true))
And("the granted views should be the same")
viewsIdsToGrant.toSet should equal(viewsInfo.views.map(_.id).toSet)
//we revoke access to the granted views for the next tests
revokeUserAccessToAllViews(bankId, bankAccount.id, userId)
}
scenario("we cannot grant a user access to a list of views on an bank account because the user does not exist", API1_2, PostPermissions) {
Given("We will use an access token with a random user Id")
val bankId = randomBank
val bankAccount : AccountJSON = randomPrivateAccount(bankId)
val userId = urlEncode(randomString(5))
val viewsIdsToGrant= randomViewsIdsToGrant(bankId, bankAccount.id)
When("the request is sent")
val reply = grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant)
Then("we should get a 400 ok code")
reply.code should equal (400)
And("we should get an error message")
reply.body.extract[ErrorMessage].error.nonEmpty should equal (true)
}
scenario("we cannot grant a user access to a list of views on an bank account because they don't exist", API1_2, PostPermission) {
Given("We will use an access token")
val bankId = randomBank
val bankAccount : AccountJSON = randomPrivateAccount(bankId)
val userId = urlEncode(user3.email)
val viewsIdsToGrant= List(randomString(3),randomString(3))
When("the request is sent")
val reply = grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant)
Then("we should get a 400 ok code")
reply.code should equal (400)
And("we should get an error message")
reply.body.extract[ErrorMessage].error.nonEmpty should equal (true)
}
scenario("we cannot grant a user access to a list of views on an bank account because some views don't exist", API1_2, PostPermission) {
Given("We will use an access token")
val bankId = randomBank
val bankAccount : AccountJSON = randomPrivateAccount(bankId)
val userId = urlEncode(user3.email)
val viewsIdsToGrant= randomViewsIdsToGrant(bankId, bankAccount.id) ++ List(randomString(3),randomString(3))
When("the request is sent")
val reply = grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant)
Then("we should get a 400 ok code")
reply.code should equal (400)
And("we should get an error message")
reply.body.extract[ErrorMessage].error.nonEmpty should equal (true)
}
scenario("we cannot grant a user access to a list of views on an bank account because the user does not have owner view access", API1_2, PostPermission) {
Given("We will use an access token")
val bankId = randomBank
val bankAccount : AccountJSON = randomPrivateAccount(bankId)
val userId = urlEncode(user3.email)
val viewsIdsToGrant= randomViewsIdsToGrant(bankId, bankAccount.id) ++ List(randomString(3),randomString(3))
When("the request is sent")
val reply = grantUserAccessToViewsWithWrongUser(bankId, bankAccount.id, userId, viewsIdsToGrant)
Then("we should get a 400 ok code")
reply.code should equal (400)
And("we should get an error message")
reply.body.extract[ErrorMessage].error.nonEmpty should equal (true)
}
}
feature("Revoke a user access to a view on a bank account"){
scenario("we will revoke the access of a user to a view on an bank account", API1_2, DeletePermission) {
Given("We will use an access token")
@ -1610,6 +1708,7 @@ class API1_2Test extends ServerSetup{
reply.code should equal (400)
}
}
feature("We get the list of the other bank accounts linked with a bank account"){
scenario("we will get the other bank accounts of a bank account", API1_2, GetOtherBankAccounts) {
Given("We will use an access token")