mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 19:36:50 +00:00
commit
d79c8f2c6a
@ -769,8 +769,8 @@ display_internal_errors=false
|
||||
# oauth2.keycloak.well_known=http://localhost:7070/realms/master/.well-known/openid-configuration
|
||||
# Used to sync IAM of OBP-API and IAM of Keycloak
|
||||
# oauth2.keycloak.source_of_truth = false
|
||||
# LIst of resource access objects allowed to sync IAM of OBP-API and IAM of Keycloak
|
||||
# oauth2.keycloak.resource_access_name = SOME_NAME
|
||||
# Resource access object allowed to sync IAM of OBP-API and IAM of Keycloak
|
||||
# oauth2.keycloak.resource_access_key_name_to_trust = open-bank-project
|
||||
# ------------------------------------------------------------------------------ OAuth 2 ------
|
||||
|
||||
# -- PSU Authentication methods --------------------------------------------------------------
|
||||
|
||||
@ -518,7 +518,7 @@ object OAuth2Login extends RestHelper with MdcLoggable {
|
||||
private def addScopesToConsumer(token: String, consumerPrimaryKey: Long): Unit = {
|
||||
val sourceOfTruth = APIUtil.getPropsAsBoolValue(nameOfProperty = "oauth2.keycloak.source_of_truth", defaultValue = false)
|
||||
// Consumers allowed to use the source of truth feature
|
||||
val resourceAccessName = APIUtil.getPropsValue(nameOfProperty = "oauth2.keycloak.resource_access_name", "")
|
||||
val resourceAccessName = APIUtil.getPropsValue(nameOfProperty = "oauth2.keycloak.resource_access_key_name_to_trust", "open-bank-project")
|
||||
val consumerId = getClaim(name = "azp", idToken = token).getOrElse("")
|
||||
if(sourceOfTruth) {
|
||||
logger.debug("Extracting roles from Access Token")
|
||||
|
||||
@ -216,10 +216,11 @@ object OpenIdConnect extends OBPRestHelper with MdcLoggable {
|
||||
private def getOrCreateResourceUser(idToken: String): Box[User] = {
|
||||
val uniqueIdGivenByProvider = JwtUtil.getSubject(idToken)
|
||||
val provider = Hydra.resolveProvider(idToken)
|
||||
val preferredUsername = JwtUtil.getOptionalClaim("preferred_username", idToken)
|
||||
Users.users.vend.getUserByProviderId(provider = provider, idGivenByProvider = uniqueIdGivenByProvider.getOrElse("")).or { // Find a user
|
||||
Users.users.vend.createResourceUser( // Otherwise create a new one
|
||||
provider = provider,
|
||||
providerId = uniqueIdGivenByProvider,
|
||||
providerId = preferredUsername.orElse(uniqueIdGivenByProvider),
|
||||
createdByConsentId = None,
|
||||
name = uniqueIdGivenByProvider,
|
||||
email = getClaim(name = "email", idToken = idToken),
|
||||
|
||||
@ -996,6 +996,10 @@ object ApiRole extends MdcLoggable{
|
||||
lazy val canUpdateConsentAccountAccessAtOneBank = CanUpdateConsentAccountAccessAtOneBank()
|
||||
case class CanUpdateConsentAccountAccessAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canUpdateConsentAccountAccessAtAnyBank = CanUpdateConsentAccountAccessAtAnyBank()
|
||||
case class CanUpdateConsentUserAtOneBank(requiresBankId: Boolean = true) extends ApiRole
|
||||
lazy val canUpdateConsentUserAtOneBank = CanUpdateConsentUserAtOneBank()
|
||||
case class CanUpdateConsentUserAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
|
||||
lazy val canUpdateConsentUserAtAnyBank = CanUpdateConsentUserAtAnyBank()
|
||||
case class CanRevokeConsentAtBank(requiresBankId: Boolean = true) extends ApiRole
|
||||
lazy val canRevokeConsentAtBank = CanRevokeConsentAtBank()
|
||||
case class CanGetConsentsAtOneBank(requiresBankId: Boolean = true) extends ApiRole
|
||||
|
||||
@ -4,6 +4,7 @@ import java.text.SimpleDateFormat
|
||||
import java.util.{Date, UUID}
|
||||
import code.api.berlin.group.v1_3.JSONFactory_BERLIN_GROUP_1_3.{ConsentAccessJson, PostConsentJson}
|
||||
import code.api.util.ApiRole.{canCreateEntitlementAtAnyBank, canCreateEntitlementAtOneBank}
|
||||
import code.api.util.ErrorMessages.InvalidConnectorResponse
|
||||
import code.api.v3_1_0.{PostConsentBodyCommonJson, PostConsentEntitlementJsonV310, PostConsentViewJsonV310}
|
||||
import code.api.{Constant, RequestHeader}
|
||||
import code.bankconnectors.Connector
|
||||
@ -20,7 +21,7 @@ import code.views.Views
|
||||
import com.nimbusds.jwt.JWTClaimsSet
|
||||
import com.openbankproject.commons.ExecutionContext.Implicits.global
|
||||
import com.openbankproject.commons.model._
|
||||
import net.liftweb.common.{Box, Empty, Failure, Full}
|
||||
import net.liftweb.common.{Box, Empty, Failure, Full, ParamFailure}
|
||||
import net.liftweb.http.provider.HTTPParam
|
||||
import net.liftweb.json.JsonParser.ParseException
|
||||
import net.liftweb.json.{Extraction, MappingException, compactRender, parse}
|
||||
@ -742,9 +743,9 @@ object Consent extends MdcLoggable {
|
||||
Full(CertificateUtil.jwtWithHmacProtection(jwtClaims, secret))
|
||||
}
|
||||
}
|
||||
def updateBerlinGroupConsentJWT(access: ConsentAccessJson,
|
||||
consent: MappedConsent,
|
||||
callContext: Option[CallContext]): Future[Box[String]] = {
|
||||
def updateAccountAccessOfBerlinGroupConsentJWT(access: ConsentAccessJson,
|
||||
consent: MappedConsent,
|
||||
callContext: Option[CallContext]): Future[Box[String]] = {
|
||||
implicit val dateFormats = CustomJsonFormats.formats
|
||||
val payloadToUpdate: Box[ConsentJWT] = JwtUtil.getSignedPayloadAsJson(consent.jsonWebToken) // Payload as JSON string
|
||||
.map(net.liftweb.json.parse(_).extract[ConsentJWT]) // Extract case class
|
||||
@ -754,9 +755,10 @@ object Consent extends MdcLoggable {
|
||||
val accounts: List[Future[ConsentView]] = access.accounts.getOrElse(Nil) map { account =>
|
||||
Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount =>
|
||||
logger.debug(s"createBerlinGroupConsentJWT.accounts.bankAccount: $bankAccount")
|
||||
val error = s"${InvalidConnectorResponse} IBAN: ${account.iban.getOrElse("")} ${handleBox(bankAccount._1)}"
|
||||
ConsentView(
|
||||
bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).openOrThrowException(error),
|
||||
view_id = Constant.SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID
|
||||
)
|
||||
}
|
||||
@ -764,9 +766,10 @@ object Consent extends MdcLoggable {
|
||||
val balances: List[Future[ConsentView]] = access.balances.getOrElse(Nil) map { account =>
|
||||
Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount =>
|
||||
logger.debug(s"createBerlinGroupConsentJWT.balances.bankAccount: $bankAccount")
|
||||
val error = s"${InvalidConnectorResponse} IBAN: ${account.iban.getOrElse("")} ${handleBox(bankAccount._1)}"
|
||||
ConsentView(
|
||||
bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).openOrThrowException(error),
|
||||
view_id = Constant.SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID
|
||||
)
|
||||
}
|
||||
@ -774,9 +777,10 @@ object Consent extends MdcLoggable {
|
||||
val transactions: List[Future[ConsentView]] = access.transactions.getOrElse(Nil) map { account =>
|
||||
Connector.connector.vend.getBankAccountByIban(account.iban.getOrElse(""), callContext) map { bankAccount =>
|
||||
logger.debug(s"createBerlinGroupConsentJWT.transactions.bankAccount: $bankAccount")
|
||||
val error = s"${InvalidConnectorResponse} IBAN: ${account.iban.getOrElse("")} ${handleBox(bankAccount._1)}"
|
||||
ConsentView(
|
||||
bank_id = bankAccount._1.map(_.bankId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).getOrElse(""),
|
||||
account_id = bankAccount._1.map(_.accountId.value).openOrThrowException(error),
|
||||
view_id = Constant.SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID
|
||||
)
|
||||
}
|
||||
@ -793,6 +797,20 @@ object Consent extends MdcLoggable {
|
||||
}
|
||||
}
|
||||
}
|
||||
def updateUserIdOfBerlinGroupConsentJWT(createdByUserId: String,
|
||||
consent: MappedConsent,
|
||||
callContext: Option[CallContext]): Future[Box[String]] = {
|
||||
implicit val dateFormats = CustomJsonFormats.formats
|
||||
val payloadToUpdate: Box[ConsentJWT] = JwtUtil.getSignedPayloadAsJson(consent.jsonWebToken) // Payload as JSON string
|
||||
.map(net.liftweb.json.parse(_).extract[ConsentJWT]) // Extract case class
|
||||
|
||||
Future {
|
||||
val updatedPayload = payloadToUpdate.map(i => i.copy(createdByUserId = createdByUserId)) // Update only the field "createdByUserId"
|
||||
val jwtPayloadAsJson = compactRender(Extraction.decompose(updatedPayload))
|
||||
val jwtClaims: JWTClaimsSet = JWTClaimsSet.parse(jwtPayloadAsJson)
|
||||
Full(CertificateUtil.jwtWithHmacProtection(jwtClaims, consent.secret))
|
||||
}
|
||||
}
|
||||
|
||||
def createUKConsentJWT(
|
||||
user: Option[User],
|
||||
@ -958,4 +976,28 @@ object Consent extends MdcLoggable {
|
||||
consentsOfBank
|
||||
}
|
||||
|
||||
/*
|
||||
// Example Usage
|
||||
val box1: Box[String] = Full("Hello, World!")
|
||||
val box2: Box[String] = Failure("Something went wrong")
|
||||
val box3: Box[String] = ParamFailure("Invalid parameter", Empty, Empty, "UserID=123")
|
||||
|
||||
println(handleBox(box1)) // Output: "Success: Hello, World!"
|
||||
println(handleBox(box2)) // Output: "Error: Something went wrong"
|
||||
println(handleBox(box3)) // Output: "Error: Invalid parameter (Parameter: UserID=123)"
|
||||
*/
|
||||
def handleBox[T](box: Box[T]): String = box match {
|
||||
case Full(value) =>
|
||||
s"Success: $value"
|
||||
case Empty =>
|
||||
"Error: Box is empty"
|
||||
case ParamFailure(msg, _, _, param) =>
|
||||
s"Error: $msg (Parameter: $param)"
|
||||
case Failure(msg, _, _) =>
|
||||
s"Error: $msg"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -143,6 +143,24 @@ object JwtUtil extends MdcLoggable {
|
||||
""
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This fuction gets an arbitrary claim
|
||||
* @param name The name of the claim we want to get
|
||||
* @param jwtToken JSON Web Token (JWT) as a String value
|
||||
* @return The claim we requested
|
||||
*/
|
||||
def getOptionalClaim(name: String, jwtToken: String): Option[String] = {
|
||||
try {
|
||||
val signedJWT = SignedJWT.parse(jwtToken)
|
||||
// claims extraction...
|
||||
Some(signedJWT.getJWTClaimsSet.getStringClaim(name))
|
||||
} catch {
|
||||
case e: Exception =>
|
||||
logger.debug(msg = s"code.api.util.JwtUtil.getClaim: $name")
|
||||
logger.debug(e)
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Issuer Identifier for the Issuer of the response.
|
||||
|
||||
@ -726,16 +726,16 @@ object NewStyle extends MdcLoggable{
|
||||
}
|
||||
|
||||
def updateConsumer(id: Long,
|
||||
key: Option[String],
|
||||
secret: Option[String],
|
||||
isActive: Option[Boolean],
|
||||
name: Option[String],
|
||||
appType: Option[AppType],
|
||||
description: Option[String],
|
||||
developerEmail: Option[String],
|
||||
redirectURL: Option[String],
|
||||
createdByUserId: Option[String],
|
||||
logoURL: Option[String],
|
||||
key: Option[String] = None,
|
||||
secret: Option[String] = None,
|
||||
isActive: Option[Boolean] = None,
|
||||
name: Option[String] = None,
|
||||
appType: Option[AppType] = None,
|
||||
description: Option[String] = None,
|
||||
developerEmail: Option[String] = None,
|
||||
redirectURL: Option[String] = None,
|
||||
createdByUserId: Option[String] = None,
|
||||
logoURL: Option[String] = None,
|
||||
callContext: Option[CallContext]): Future[Consumer] = {
|
||||
Future(Consumers.consumers.vend.updateConsumer(id, key, secret, isActive, name, appType, description, developerEmail, redirectURL, createdByUserId, logoURL)) map {
|
||||
unboxFullOrFail(_, callContext, UpdateConsumerError, 404)
|
||||
|
||||
@ -1638,7 +1638,12 @@ trait APIMethods210 {
|
||||
consumer.createdByUserId.equals(u.userId)
|
||||
}
|
||||
//update the redirectURL and isactive (set to false when change redirectUrl) field in consumer table
|
||||
updatedConsumer <- NewStyle.function.updateConsumer(consumer.id.get, None, None, Some(APIUtil.getPropsAsBoolValue("consumers_enabled_by_default", false)), None, None, None, None, Some(postJson.redirect_url), None, None, callContext)
|
||||
updatedConsumer <- NewStyle.function.updateConsumer(
|
||||
id = consumer.id.get,
|
||||
isActive = Some(APIUtil.getPropsAsBoolValue("consumers_enabled_by_default", false)),
|
||||
redirectURL = Some(postJson.redirect_url),
|
||||
callContext = callContext
|
||||
)
|
||||
} yield {
|
||||
val json = JSONFactory210.createConsumerJSON(updatedConsumer)
|
||||
(json, HttpCode.`200`(callContext))
|
||||
|
||||
@ -22,9 +22,9 @@ import code.api.v2_1_0.ConsumerRedirectUrlJSON
|
||||
import code.api.v3_0_0.JSONFactory300
|
||||
import code.api.v3_0_0.JSONFactory300.createAggregateMetricJson
|
||||
import code.api.v3_1_0.{ConsentChallengeJsonV310, ConsentJsonV310}
|
||||
import code.api.v3_1_0.JSONFactory310.{createBadLoginStatusJson, createRefreshUserJson}
|
||||
import code.api.v3_1_0.JSONFactory310.{createBadLoginStatusJson, createConsumerJSON, createRefreshUserJson}
|
||||
import code.api.v4_0_0.JSONFactory400.{createAccountBalancesJson, createBalancesJson, createNewCoreBankAccountJson}
|
||||
import code.api.v4_0_0.{JSONFactory400, PostAccountAccessJsonV400, PostApiCollectionJson400, PutConsentStatusJsonV400, RevokedJsonV400}
|
||||
import code.api.v4_0_0.{JSONFactory400, PostAccountAccessJsonV400, PostApiCollectionJson400, PutConsentStatusJsonV400, PutConsentUserJsonV400, RevokedJsonV400}
|
||||
import code.api.v5_0_0.JSONFactory500
|
||||
import code.api.v5_1_0.JSONFactory510.{createConsentsInfoJsonV510, createConsentsJsonV510, createRegulatedEntitiesJson, createRegulatedEntityJson}
|
||||
import code.atmattribute.AtmAttribute
|
||||
@ -1409,15 +1409,92 @@ trait APIMethods510 {
|
||||
consentJson.access.accounts.isEmpty &&
|
||||
consentJson.access.balances.isEmpty &&
|
||||
consentJson.access.transactions.isEmpty
|
||||
}
|
||||
}
|
||||
consentJWT <- Consent.updateBerlinGroupConsentJWT(
|
||||
}
|
||||
consentJWT <- Consent.updateAccountAccessOfBerlinGroupConsentJWT(
|
||||
consentJson.access,
|
||||
consent,
|
||||
cc.callContext
|
||||
) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
consent,
|
||||
cc.callContext
|
||||
) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
updatedConsent <- Future(Consents.consentProvider.vend.setJsonWebToken(consent.consentId, consentJWT)) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
} yield {
|
||||
(
|
||||
ConsentJsonV310(
|
||||
updatedConsent.consentId,
|
||||
updatedConsent.jsonWebToken,
|
||||
updatedConsent.status
|
||||
),
|
||||
HttpCode.`200`(cc.callContext)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
updateConsentUserIdByConsentId,
|
||||
implementedInApiVersion,
|
||||
nameOf(updateConsentUserIdByConsentId),
|
||||
"PUT",
|
||||
"/management/banks/BANK_ID/consents/CONSENT_ID/created-by-user",
|
||||
"Update Consent Created by User by CONSENT_ID",
|
||||
s"""
|
||||
|
|
||||
|This endpoint is used to update the Created by User of Consent.
|
||||
|
|
||||
|${authenticationRequiredMessage(true)}
|
||||
|
|
||||
|""",
|
||||
PutConsentUserJsonV400(user_id = "ed7a7c01-db37-45cc-ba12-0ae8891c195c"),
|
||||
ConsentChallengeJsonV310(
|
||||
consent_id = "9d429899-24f5-42c8-8565-943ffa6a7945",
|
||||
jwt = "eyJhbGciOiJIUzI1NiJ9.eyJlbnRpdGxlbWVudHMiOltdLCJjcmVhdGVkQnlVc2VySWQiOiJhYjY1MzlhOS1iMTA1LTQ0ODktYTg4My0wYWQ4ZDZjNjE2NTciLCJzdWIiOiIyMWUxYzhjYy1mOTE4LTRlYWMtYjhlMy01ZTVlZWM2YjNiNGIiLCJhdWQiOiJlanpuazUwNWQxMzJyeW9tbmhieDFxbXRvaHVyYnNiYjBraWphanNrIiwibmJmIjoxNTUzNTU0ODk5LCJpc3MiOiJodHRwczpcL1wvd3d3Lm9wZW5iYW5rcHJvamVjdC5jb20iLCJleHAiOjE1NTM1NTg0OTksImlhdCI6MTU1MzU1NDg5OSwianRpIjoiMDlmODhkNWYtZWNlNi00Mzk4LThlOTktNjYxMWZhMWNkYmQ1Iiwidmlld3MiOlt7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAxIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifSx7ImFjY291bnRfaWQiOiJtYXJrb19wcml2aXRlXzAyIiwiYmFua19pZCI6ImdoLjI5LnVrLngiLCJ2aWV3X2lkIjoib3duZXIifV19.8cc7cBEf2NyQvJoukBCmDLT7LXYcuzTcSYLqSpbxLp4",
|
||||
status = "AUTHORISED"
|
||||
),
|
||||
List(
|
||||
$UserNotLoggedIn,
|
||||
$BankNotFound,
|
||||
InvalidJsonFormat,
|
||||
ConsentNotFound,
|
||||
InvalidConnectorResponse,
|
||||
UnknownError
|
||||
),
|
||||
apiTagConsent :: apiTagPSD2AIS :: Nil,
|
||||
Some(List(canUpdateConsentUserAtOneBank, canUpdateConsentUserAtAnyBank))
|
||||
)
|
||||
|
||||
lazy val updateConsentUserIdByConsentId: OBPEndpoint = {
|
||||
case "management" :: "banks" :: BankId(bankId) :: "consents" :: consentId :: "created-by-user" :: Nil JsonPut json -> _ =>
|
||||
cc =>
|
||||
implicit val ec = EndpointContext(Some(cc))
|
||||
for {
|
||||
consent: MappedConsent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
|
||||
unboxFullOrFail(_, cc.callContext, s"$ConsentNotFound ($consentId)", 404)
|
||||
}
|
||||
consentJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $PutConsentUserJsonV400 ", 400, cc.callContext) {
|
||||
json.extract[PutConsentUserJsonV400]
|
||||
}
|
||||
user <- Users.users.vend.getUserByUserIdFuture(consentJson.user_id) map {
|
||||
x => unboxFullOrFail(x, cc.callContext, s"$UserNotFoundByUserId Current UserId(${consentJson.user_id})")
|
||||
}
|
||||
consent <- Future(Consents.consentProvider.vend.getConsentByConsentId(consentId)) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
_ <- Helper.booleanToFuture(ConsentUserAlreadyAdded, cc = cc.callContext) {
|
||||
consent.userId != null
|
||||
}
|
||||
consent <- Future(Consents.consentProvider.vend.updateConsentUser(consentId, user)) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
consentJWT <- Consent.updateUserIdOfBerlinGroupConsentJWT(
|
||||
consentJson.user_id,
|
||||
consent,
|
||||
cc.callContext
|
||||
) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
updatedConsent <- Future(Consents.consentProvider.vend.setJsonWebToken(consent.consentId, consentJWT)) map {
|
||||
i => connectorEmptyResponse(i, cc.callContext)
|
||||
}
|
||||
@ -2683,12 +2760,10 @@ trait APIMethods510 {
|
||||
}
|
||||
//update the redirectURL and isactive (set to false when change redirectUrl) field in consumer table
|
||||
updatedConsumer <- NewStyle.function.updateConsumer(
|
||||
consumer.id.get, None, None, Some(APIUtil.getPropsAsBoolValue("consumers_enabled_by_default", false)),
|
||||
None, None, None, None,
|
||||
Some(postJson.redirect_url),
|
||||
None,
|
||||
None,
|
||||
callContext
|
||||
id = consumer.id.get,
|
||||
isActive = Some(APIUtil.getPropsAsBoolValue("consumers_enabled_by_default", defaultValue = false)),
|
||||
redirectURL = Some(postJson.redirect_url),
|
||||
callContext = callContext
|
||||
)
|
||||
} yield {
|
||||
val json = JSONFactory510.createConsumerJSON(updatedConsumer)
|
||||
@ -2734,28 +2809,53 @@ trait APIMethods510 {
|
||||
json.extract[ConsumerLogoUrlJson]
|
||||
}
|
||||
consumer <- NewStyle.function.getConsumerByConsumerId(consumerId, callContext)
|
||||
//only the developer that created the Consumer should be able to edit it
|
||||
_ <- Helper.booleanToFuture(UserNoPermissionUpdateConsumer, 400, callContext) {
|
||||
consumer.createdByUserId.equals(u.userId)
|
||||
}
|
||||
updatedConsumer <- NewStyle.function.updateConsumer(
|
||||
consumer.id.get,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
logoURL = Some(postJson.logo_url),
|
||||
callContext)
|
||||
id = consumer.id.get,
|
||||
logoURL = Some(postJson.logo_url),
|
||||
callContext = callContext
|
||||
)
|
||||
} yield {
|
||||
(JSONFactory510.createConsumerJSON(updatedConsumer), HttpCode.`200`(callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
staticResourceDocs += ResourceDoc(
|
||||
getConsumer,
|
||||
implementedInApiVersion,
|
||||
nameOf(getConsumer),
|
||||
"GET",
|
||||
"/management/consumers/CONSUMER_ID",
|
||||
"Get Consumer",
|
||||
s"""Get the Consumer specified by CONSUMER_ID.
|
||||
|
|
||||
|""",
|
||||
EmptyBody,
|
||||
consumerJSON,
|
||||
List(
|
||||
$UserNotLoggedIn,
|
||||
UserHasMissingRoles,
|
||||
ConsumerNotFoundByConsumerId,
|
||||
UnknownError
|
||||
),
|
||||
List(apiTagConsumer),
|
||||
Some(List(canGetConsumers)))
|
||||
|
||||
|
||||
lazy val getConsumer: OBPEndpoint = {
|
||||
case "management" :: "consumers" :: consumerId :: Nil JsonGet _ => {
|
||||
cc =>
|
||||
implicit val ec = EndpointContext(Some(cc))
|
||||
for {
|
||||
consumer <- NewStyle.function.getConsumerByConsumerId(consumerId, cc.callContext)
|
||||
user <- Users.users.vend.getUserByUserIdFuture(consumer.createdByUserId.get)
|
||||
} yield {
|
||||
(createConsumerJSON(consumer, user), HttpCode.`200`(cc.callContext))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resourceDocs += ResourceDoc(
|
||||
getConsumers,
|
||||
implementedInApiVersion,
|
||||
|
||||
@ -125,6 +125,7 @@ object MappedConsumersProvider extends ConsumersProvider with MdcLoggable {
|
||||
val toDate = queryParams.collect { case OBPToDate(date) => By_<=(Consumer.createdAt, date) }.headOption
|
||||
val azp = queryParams.collect { case OBPAzp(value) => By(Consumer.azp, value) }.headOption
|
||||
val iss = queryParams.collect { case OBPIss(value) => By(Consumer.iss, value) }.headOption
|
||||
val consumerId = queryParams.collect { case OBPConsumerId(value) => By(Consumer.consumerId, value) }.headOption
|
||||
val ordering = queryParams.collect {
|
||||
case OBPOrdering(_, direction) =>
|
||||
direction match {
|
||||
@ -134,7 +135,7 @@ object MappedConsumersProvider extends ConsumersProvider with MdcLoggable {
|
||||
}
|
||||
|
||||
val mapperParams: Seq[QueryParam[Consumer]] =
|
||||
Seq(limit.toSeq, offset.toSeq, fromDate.toSeq, toDate.toSeq, ordering, azp.toSeq, iss.toSeq).flatten
|
||||
Seq(limit.toSeq, offset.toSeq, fromDate.toSeq, toDate.toSeq, ordering, azp.toSeq, iss.toSeq, consumerId.toSeq).flatten
|
||||
|
||||
Consumer.findAll(mapperParams: _*)
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.ApiRole.{canCreateConsumer, canGetConsumers, canUpdateConsumerLogoUrl, canUpdateConsumerRedirectUrl}
|
||||
import code.api.util.ErrorMessages.{InvalidJsonFormat, UserNotLoggedIn}
|
||||
import code.api.v3_1_0.ConsumerJsonV310
|
||||
import code.api.v5_1_0.OBPAPI5_1_0.Implementations5_1_0
|
||||
import code.entitlement.Entitlement
|
||||
import com.github.dwickern.macros.NameOf.nameOf
|
||||
@ -50,23 +51,24 @@ class ConsumerTest extends V510ServerSetup {
|
||||
object ApiEndpoint2 extends Tag(nameOf(Implementations5_1_0.getConsumers))
|
||||
object ApiEndpoint3 extends Tag(nameOf(Implementations5_1_0.updateConsumerRedirectURL))
|
||||
object ApiEndpoint4 extends Tag(nameOf(Implementations5_1_0.updateConsumerLogoURL))
|
||||
object GetConsumer extends Tag(nameOf(Implementations5_1_0.getConsumer))
|
||||
|
||||
feature("Test all error cases ") {
|
||||
scenario("We test the authentication errors", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) {
|
||||
scenario("We test the authentication errors", GetConsumer, ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) {
|
||||
When("We make a request v5.1.0")
|
||||
lazy val postApiCollectionJson = SwaggerDefinitionsJSON.postApiCollectionJson400
|
||||
val requestApiEndpoint1 = (v5_1_0_Request / "management" / "consumers").POST
|
||||
val responseApiEndpoint1 = makePostRequest(requestApiEndpoint1, write(postApiCollectionJson))
|
||||
|
||||
val requestApiEndpoint2 = (v5_1_0_Request / "management" / "consumers").GET
|
||||
val responseApiEndpoint2 = makePostRequest(requestApiEndpoint2, write(postApiCollectionJson))
|
||||
val responseApiEndpoint2 = makeGetRequest(requestApiEndpoint2)
|
||||
|
||||
val requestApiEndpoint3= (v5_1_0_Request / "management" / "consumers" / "CONSUMER_ID" / "consumer" / "redirect_url").PUT
|
||||
val responseApiEndpoint3 = makePutRequest(requestApiEndpoint3, write(postApiCollectionJson))
|
||||
|
||||
val requestApiEndpoint4 = (v5_1_0_Request /"management" / "consumers" / "CONSUMER_ID" / "consumer" / "logo_url").PUT
|
||||
val responseApiEndpoint4 = makePutRequest(requestApiEndpoint4, write(postApiCollectionJson))
|
||||
|
||||
|
||||
Then(s"we should get the error messages")
|
||||
responseApiEndpoint1.code should equal(401)
|
||||
responseApiEndpoint2.code should equal(401)
|
||||
@ -76,9 +78,15 @@ class ConsumerTest extends V510ServerSetup {
|
||||
responseApiEndpoint2.body.toString contains(s"$UserNotLoggedIn") should be (true)
|
||||
responseApiEndpoint3.body.toString contains(s"$UserNotLoggedIn") should be (true)
|
||||
responseApiEndpoint4.body.toString contains(s"$UserNotLoggedIn") should be (true)
|
||||
|
||||
// Endpoint GetConsumer
|
||||
val requestApiEndpoint5 = (v5_1_0_Request / "management" / "consumers" / "whatever").GET
|
||||
val responseApiEndpoint5 = makeGetRequest(requestApiEndpoint5)
|
||||
responseApiEndpoint5.code should equal(401)
|
||||
responseApiEndpoint5.body.toString contains(s"$UserNotLoggedIn") should be (true)
|
||||
}
|
||||
|
||||
scenario("We test the missing roles errors", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) {
|
||||
scenario("We test the missing roles errors", GetConsumer, ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) {
|
||||
When("We make a request v5.1.0")
|
||||
|
||||
lazy val wrongJsonForTesting = SwaggerDefinitionsJSON.routing
|
||||
@ -103,6 +111,12 @@ class ConsumerTest extends V510ServerSetup {
|
||||
responseApiEndpoint3.body.toString contains(s"$canUpdateConsumerRedirectUrl") should be (true)
|
||||
responseApiEndpoint4.code should equal(403)
|
||||
responseApiEndpoint4.body.toString contains(s"$canUpdateConsumerLogoUrl") should be (true)
|
||||
|
||||
// Endpoint GetConsumer
|
||||
val requestApiEndpoint5 = (v5_1_0_Request / "management" / "consumers" / "whatever").GET <@ user1
|
||||
val responseApiEndpoint5 = makeGetRequest(requestApiEndpoint5)
|
||||
responseApiEndpoint5.code should equal(403)
|
||||
responseApiEndpoint5.body.toString contains (s"$canGetConsumers") should be(true)
|
||||
}
|
||||
|
||||
scenario("We added the proper roles, but wrong json", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) {
|
||||
@ -133,7 +147,7 @@ class ConsumerTest extends V510ServerSetup {
|
||||
}
|
||||
|
||||
feature(s"test all successful cases") {
|
||||
scenario("we create, update and get consumers", ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) {
|
||||
scenario("we create, update and get consumers", GetConsumer, ApiEndpoint1, ApiEndpoint2, ApiEndpoint3, ApiEndpoint4, VersionOfApi) {
|
||||
|
||||
When("we first grant the missing roles:")
|
||||
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, canCreateConsumer.toString)
|
||||
@ -177,6 +191,11 @@ class ConsumerTest extends V510ServerSetup {
|
||||
val consumers = responseApiEndpoint2.body.extract[ConsumersJsonV510].consumers
|
||||
consumers.find(_.consumer_id ==consumerId).head.redirect_url shouldBe(consumerRedirectUrlJSON.redirect_url)
|
||||
consumers.find(_.consumer_id ==consumerId).head.logo_url.head shouldBe(consumerLogoUrlJson.logo_url)
|
||||
|
||||
// Endpoint GetConsumer
|
||||
val requestApiEndpoint5 = (v5_1_0_Request / "management" / "consumers" / consumerId).GET <@ user1
|
||||
val consumer = makeGetRequest(requestApiEndpoint5).body.extract[ConsumerJsonV310]
|
||||
consumer.consumer_id shouldBe consumerId
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user