Add bank level entitlements / roles #42 - without item number 7

This commit is contained in:
Marko Milic 2016-06-03 17:01:55 +02:00
parent 81d57c91bb
commit 7b2728e0cc
9 changed files with 207 additions and 2 deletions

View File

@ -170,3 +170,7 @@ apiOptions.getTransactionTypesIsPublic = true
# Default Bank. Incase the server wants to support a default bank so developers don't have to specify BANK_ID
# e.g. developers could use /my/accounts as well as /my/banks/BANK_ID/accounts
defaultBank.bank_id=THE_DEFAULT_BANK_ID
# Super Admin Users (not database so we don't have to edit database)
super_admin_user_ids=USER_ID1,USER_ID2,

View File

@ -42,6 +42,7 @@ import code.atms.MappedAtm
import code.branches.MappedBranch
import code.crm.MappedCrmEvent
import code.customer.{MappedCustomer, MappedCustomerMessage}
import code.entitlement.MappedEntitlement
import code.kycdocuments.MappedKycDocument
import code.kycmedias.MappedKycMedia
import code.kycchecks.MappedKycCheck
@ -419,5 +420,6 @@ object ToSchemify {
MappedSocialMedia,
MappedTransactionType,
MappedMeeting,
MappedUserCustomerLink)
MappedUserCustomerLink,
MappedEntitlement)
}

View File

@ -34,6 +34,7 @@ package code.api.util
import code.api.Constant._
import code.api.v1_2.ErrorMessage
import code.entitlement.Entitlements
import code.metrics.APIMetrics
import code.model._
import dispatch.url
@ -572,4 +573,13 @@ object APIUtil extends Loggable {
halLinksJson
}
def isSuperAdmin(user_id: String) : Boolean = {
val user_ids = Props.get("super_admin_user_ids", "super_admin_user_ids is not defined").split(",").map(_.trim).toList
user_ids.filter(_ == user_id).length > 0
}
def hasEntitlement(bankId: String, userId: String, role: ApiRole): Boolean = {
Entitlements.entitlementProvider.vend.getEntitlement(bankId, userId, role.toString).isEmpty
}
}

View File

@ -0,0 +1,18 @@
package code.api.util
sealed trait ApiRole
object ApiRole {
case object CanSearchAllTransactions extends ApiRole
case object CanSearchAllAccounts extends ApiRole
case object CanQueryOtherUser extends ApiRole
def valueOf(value: String): ApiRole = value match {
case "CanSearchAllTransactions" => CanSearchAllTransactions
case "CanSearchAllAccounts" => CanSearchAllAccounts
case "CanQueryOtherUser" => CanQueryOtherUser
case _ => throw new IllegalArgumentException()
}
}

View File

@ -6,6 +6,7 @@ import java.util.Calendar
import code.TransactionTypes.TransactionType
import code.api.APIFailure
import code.api.util.APIUtil._
import code.api.util.ApiRole._
import code.api.util.ErrorMessages
import code.api.v1_2_1.OBPAPI1_2_1._
import code.api.v1_2_1.{APIMethods121, AmountOfMoneyJSON => AmountOfMoneyJSON121, JSONFactory => JSONFactory121}
@ -30,6 +31,7 @@ import code.transactionrequests.TransactionRequests
import code.meetings.Meeting
import code.usercustomerlinks.UserCustomerLink
import code.entitlement.Entitlements
import net.liftweb.common.{Full, _}
import net.liftweb.http.rest.RestHelper
@ -1614,8 +1616,79 @@ trait APIMethods200 {
}
}
resourceDocs += ResourceDoc(
addEntitlements,
apiVersion,
"addEntitlements",
"POST",
"/users/USER_ID/entitlements",
"Add role to specific user.",
"""Grants the Role to user.
|
|OAuth authentication is required and the user needs to have access to the owner view.""",
Extraction.decompose(CreateEntitlementJSON("obp-bank-x-gh", "CanQueryOtherUser")),
emptyObjectJson,
emptyObjectJson :: Nil,
false,
false,
false,
List())
lazy val addEntitlements : PartialFunction[Req, Box[User] => Box[JsonResponse]] = {
//add access for specific user to a list of views
case "users" :: userId :: "entitlements" :: Nil JsonPost json -> _ => {
user =>
for {
u <- user ?~ ErrorMessages.UserNotLoggedIn
isSuperAdmin <- booleanToBox(isSuperAdmin(u.userId)) ?~ "User is not super admin!"
postedData <- tryo{json.extract[CreateEntitlementJSON]} ?~ "wrong format JSON"
role <- tryo{valueOf(postedData.role_name)} ?~! "wrong role name"
hasEntitlement <- booleanToBox(hasEntitlement(postedData.bank_id, u.userId, role)) ?~ "Entitlement already exists"
addedEntitlement <- Entitlements.entitlementProvider.vend.addEntitlement(postedData.bank_id, u.userId, postedData.role_name)
} yield {
val viewJson = JSONFactory200.createEntitlementJSON(addedEntitlement)
successJsonResponse(Extraction.decompose(viewJson), 201)
}
}
}
resourceDocs += ResourceDoc(
getEntitlements,
apiVersion,
"getEntitlements",
"GET",
"/users/USER_ID/entitlements",
"Get Entitlement specified by USER_ID",
"""
|
|Login is required.
|
|
""".stripMargin,
emptyObjectJson,
emptyObjectJson,
emptyObjectJson :: Nil,
true,
true,
true,
List(apiTagMeeting, apiTagKyc, apiTagCustomer, apiTagUser, apiTagExperimental))
lazy val getEntitlements: PartialFunction[Req, Box[User] => Box[JsonResponse]] = {
case "users" :: userId :: "entitlements" :: Nil JsonGet _ => {
user =>
for {
u <- user ?~ ErrorMessages.UserNotLoggedIn
isSuperAdmin <- booleanToBox(isSuperAdmin(u.userId)) ?~ "User is not super admin!"
entitlements <- Entitlements.entitlementProvider.vend.getEntitlements(u.userId)
}
yield {
// Format the data as V2.0.0 json
val json = JSONFactory200.createEntitlementJSONs(entitlements)
successJsonResponse(Extraction.decompose(json))
}
}
}
///
}

View File

@ -36,6 +36,7 @@ import java.util.Date
import code.TransactionTypes.TransactionType.TransactionType
import code.meetings.Meeting
import code.entitlement.Entitlement
import code.model.dataAccess.OBPUser
import code.transactionrequests.TransactionRequests._
import net.liftweb.common.{Full, Box}
@ -310,6 +311,9 @@ case class TransactionRequestBodyJSON (
description : String
)
case class CreateEntitlementJSON(bank_id: String, role_name: String)
case class EntitlementJSON(entitlement_id: String, user_id: String, role_name: String)
case class EntitlementJSONs(list: List[EntitlementJSON])
object JSONFactory200{
@ -767,6 +771,16 @@ def createTransactionTypeJSON(transactionType : TransactionType) : TransactionTy
UserCustomerLinkJSONs(ucls.map(createUserCustomerLinkJSON))
}
def createEntitlementJSON(e: Entitlement): EntitlementJSON = {
EntitlementJSON(entitlement_id = e.entitlementId,
user_id = e.userId,
role_name = e.roleName)
}
def createEntitlementJSONs(l: List[Entitlement]) = {
EntitlementJSONs(l.map(createEntitlementJSON))
}
// Copied from 1.2.1 (import just this def instead?)
def stringOrNull(text : String) =
if(text == null || text.isEmpty)

View File

@ -170,7 +170,9 @@ object OBPAPI2_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
Implementations2_0_0.getMeeting,
Implementations2_0_0.createCustomer,
Implementations2_0_0.getCurrentUser,
Implementations2_0_0.createUserCustomerLinks
Implementations2_0_0.createUserCustomerLinks,
Implementations2_0_0.addEntitlements,
Implementations2_0_0.getEntitlements
)
routes.foreach(route => {

View File

@ -0,0 +1,25 @@
package code.entitlement
import code.model.{BankId, User}
import net.liftweb.common.Box
import net.liftweb.util.SimpleInjector
object Entitlements extends SimpleInjector {
val entitlementProvider = new Inject(buildOne _) {}
def buildOne: EntitlementProvider = MappedEntitlementsProvider
}
trait EntitlementProvider {
def getEntitlement(bankId: String, userId: String, roleName: String) : Box[Entitlement]
def getEntitlements(userId: String) : Box[List[Entitlement]]
def addEntitlement(bankId: String, userId: String, roleName: String) : Box[MappedEntitlement]
}
trait Entitlement {
def entitlementId: String
def bankId : String
def userId : String
def roleName : String
}

View File

@ -0,0 +1,57 @@
package code.entitlement
import code.util.{MappedUUID, DefaultStringField}
import net.liftweb.mapper._
import net.liftweb.common.Box
object MappedEntitlementsProvider extends EntitlementProvider {
override def getEntitlement(bankId: String, userId: String, roleName: String): Box[MappedEntitlement] = {
// Return a Box so we can handle errors later.
MappedEntitlement.find(
By(MappedEntitlement.mBankId, bankId),
By(MappedEntitlement.mUserId, userId),
By(MappedEntitlement.mRoleName, roleName)
)
}
override def getEntitlements(userId: String): Box[List[MappedEntitlement]] = {
// Return a Box so we can handle errors later.
Some(MappedEntitlement.findAll(
By(MappedEntitlement.mUserId, userId),
OrderBy(MappedEntitlement.updatedAt, Descending)))
}
override def addEntitlement(bankId: String, userId: String, roleName: String): Box[MappedEntitlement] = {
// Return a Box so we can handle errors later.
val addEntitlement = MappedEntitlement.create
.mBankId(bankId)
.mUserId(userId)
.mRoleName(roleName)
.saveMe()
Some(addEntitlement)
}
}
class MappedEntitlement extends Entitlement
with LongKeyedMapper[MappedEntitlement] with IdPK with CreatedUpdated {
def getSingleton = MappedEntitlement
object mEntitlementId extends MappedUUID(this)
object mBankId extends DefaultStringField(this)
object mUserId extends DefaultStringField(this)
object mRoleName extends DefaultStringField(this)
override def entitlementId: String = mEntitlementId.get.toString
override def bankId: String = mBankId.get
override def userId: String = mUserId.get
override def roleName: String = mRoleName.get
}
object MappedEntitlement extends MappedEntitlement with LongKeyedMetaMapper[MappedEntitlement] {
override def dbIndexes = UniqueIndex(mEntitlementId) :: UniqueIndex(mUserId, mBankId) :: super.dbIndexes
}