Consent-Id - added support for Old Style Endpoints

This commit is contained in:
Marko Milić 2019-03-22 14:04:19 +01:00
parent 22a79c3941
commit 2fbfc6c5f9
3 changed files with 73 additions and 3 deletions

View File

@ -193,8 +193,13 @@ trait OBPRestHelper extends RestHelper with MdcLoggable {
if(newStyleEndpoints(rd)) {
fn(cc)
} else if (APIUtil.hasConsentId(reqHeaders)) {
// TODO 1. Get or Create a User 2. Assign entitlements to it 3. Assign permissions
Failure(NotImplemented + RequestHeader.`Consent-Id`)
val (usr, callContext) = Consent.applyRulesOldStyle(APIUtil.getConsentId(reqHeaders), cc)
usr match {
case Full(u) => fn(callContext.copy(user = Full(u))) // Authentication is successful
case ParamFailure(a, b, c, apiFailure : APIFailure) => ParamFailure(a, b, c, apiFailure : APIFailure)
case Failure(msg, t, c) => Failure(msg, t, c)
case _ => Failure("Consent error")
}
} else if (hasAnOAuthHeader(authorization)) {
val (usr, callContext) = getUserAndCallContext(cc)
usr match {

View File

@ -1860,7 +1860,6 @@ Returns a string showed to the developer
val reqHeaders = S.request.openOrThrowException(attemptedToOpenAnEmptyBox).request.headers
val res =
if (APIUtil.hasConsentId(reqHeaders)) {
// TODO 1. Get or Create a User 2. Assign entitlements to it 3. Assign permissions
Consent.applyRules(APIUtil.getConsentId(reqHeaders), Some(cc))
} else if (hasAnOAuthHeader(cc.authReqHeaderField)) {
getUserFromOAuthHeaderFuture(cc)

View File

@ -124,6 +124,17 @@ object Consent {
email = email
)
}
private def getOrCreateUserOldStyle(subject: String, issuer: String, name: Option[String], email: Option[String]): Box[User] = {
Users.users.vend.getUserByProviderId(provider = issuer, idGivenByProvider = subject).or { // Find a user
Users.users.vend.createResourceUser( // Otherwise create a new one
provider = issuer,
providerId = Some(subject),
name = name,
email = email,
userId = None
)
}
}
private def addEntitlements(user: User, consent: ConsentJWT): Box[User] = {
def addConsentEntitlements(existingEntitlements: List[Entitlement], entitlement: Role): (Role, String) = {
@ -177,6 +188,50 @@ object Consent {
if (result.forall(_ == "Added")) Full(user) else Failure("Cannot add permissions to the user with id: " + user.userId)
}
private def hasConsentInternalOldStyle(consentIdAsJwt: String): Box[User] = {
implicit val dateFormats = net.liftweb.json.DefaultFormats
def applyConsentRules(consent: ConsentJWT): Box[User] = {
// 1. Get or Create a User
getOrCreateUserOldStyle(consent.sub, consent.iss, None, None) match {
case (Full(user)) =>
// 2. Assign entitlements to the User
addEntitlements(user, consent) match {
case (Full(user)) =>
// 3. Assign views to the User
addPermissions(user, consent)
case everythingElse =>
everythingElse
}
case _ =>
Failure("Cannot create or get the user based on: " + consentIdAsJwt)
}
}
JwtUtil.getSignedPayloadAsJson(consentIdAsJwt) match {
case Full(jsonAsString) =>
try {
val consent = net.liftweb.json.parse(jsonAsString).extract[ConsentJWT]
checkConsent(consent, consentIdAsJwt) match { // Check is it Consent-Id expired
case (Full(true)) => // OK
applyConsentRules(consent)
case failure@Failure(_, _, _) => // Handled errors
failure
case _ => // Unexpected errors
Failure("Cannot check is Consent-Id expired.")
}
} catch { // Possible exceptions
case e: ParseException => Failure("ParseException: " + e.getMessage)
case e: MappingException => Failure("MappingException: " + e.getMessage)
case e: Exception => Failure("parsing failed: " + e.getMessage)
}
case failure@Failure(_, _, _) =>
failure
case _ =>
Failure("Cannot extract data from: " + consentIdAsJwt)
}
}
private def hasConsentInternal(consentIdAsJwt: String): Future[Box[User]] = {
implicit val dateFormats = net.liftweb.json.DefaultFormats
@ -221,6 +276,9 @@ object Consent {
}
}
private def hasConsentOldStyle(consentIdAsJwt: String, calContext: CallContext): (Box[User], CallContext) = {
(hasConsentInternalOldStyle(consentIdAsJwt), calContext)
}
private def hasConsent(consentIdAsJwt: String, calContext: Option[CallContext]): Future[(Box[User], Option[CallContext])] = {
hasConsentInternal(consentIdAsJwt) map (result => (result, calContext))
}
@ -232,6 +290,14 @@ object Consent {
case (_, false) => Future((Failure("Consents are not allowed at this instance."), callContext))
case (None, _) => Future((Failure("Cannot get Consent-Id"), callContext))
}
}
def applyRulesOldStyle(consentId: Option[String], callContext: CallContext): (Box[User], CallContext) = {
val allowed = APIUtil.getPropsAsBoolValue(nameOfProperty="consents.allowed", defaultValue=false)
(consentId, allowed) match {
case (Some(consentId), true) => hasConsentOldStyle(consentId, callContext)
case (_, false) => (Failure("Consents are not allowed at this instance."), callContext)
case (None, _) => (Failure("Cannot get Consent-Id"), callContext)
}
}
}