From 5bf4467ec52577baf464ab2fd30c595fbc1935eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Wed, 24 Nov 2021 17:10:47 +0100 Subject: [PATCH] feature/Add user init action after logon WIP 1 --- .../src/main/scala/code/api/directlogin.scala | 2 + .../main/scala/code/api/openidconnect.scala | 4 +- .../main/scala/code/api/util/APIUtil.scala | 4 +- .../scala/code/api/util/AfterApiAuth.scala | 39 ++++++++++++++++++- .../code/model/dataAccess/AuthUser.scala | 6 +++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/api/directlogin.scala b/obp-api/src/main/scala/code/api/directlogin.scala index dd2196953..3ebbc274b 100644 --- a/obp-api/src/main/scala/code/api/directlogin.scala +++ b/obp-api/src/main/scala/code/api/directlogin.scala @@ -115,6 +115,8 @@ object DirectLogin extends RestHelper with MdcLoggable { val authUser = AuthUser.findUserByUsernameLocally(resourceUser.name).openOrThrowException(s"$InvalidDirectLoginParameters can not find the auth user!") AuthUser.grantEntitlementsToUseDynamicEndpointsInSpaces(authUser) AuthUser.grantEmailDomainEntitlementsToUser(authUser) + // User init actions + AfterApiAuth.userGuiLogonInitAction(Full(authUser)) } catch { case e: Throwable => // error handling, found wrong props value as early as possible. this.logger.error(s"directLogin.grantEntitlementsToUseDynamicEndpointsInSpacesInDirectLogin throw exception, details: $e" ); diff --git a/obp-api/src/main/scala/code/api/openidconnect.scala b/obp-api/src/main/scala/code/api/openidconnect.scala index a3b387bec..742e559e3 100644 --- a/obp-api/src/main/scala/code/api/openidconnect.scala +++ b/obp-api/src/main/scala/code/api/openidconnect.scala @@ -29,7 +29,7 @@ package code.api import java.net.HttpURLConnection import code.api.util.APIUtil._ -import code.api.util.{APIUtil, ErrorMessages, JwtUtil} +import code.api.util.{APIUtil, AfterApiAuth, ErrorMessages, JwtUtil} import code.consumer.Consumers import code.loginattempts.LoginAttempt import code.model.{AppType, Consumer} @@ -126,6 +126,8 @@ object OpenIdConnect extends OBPRestHelper with MdcLoggable { AuthUser.grantEmailDomainEntitlementsToUser(authUser) // Grant roles according to the props email_domain_to_space_mappings AuthUser.grantEntitlementsToUseDynamicEndpointsInSpaces(authUser) + // User init actions + AfterApiAuth.userGuiLogonInitAction(Full(authUser)) // Consumer getOrCreateConsumer(idToken, user.userId) match { case Full(consumer) => diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index a51b727fc..824579314 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -2769,9 +2769,11 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ val userIsLockedOrDeleted: Future[(Box[User], Option[CallContext])] = AfterApiAuth.checkUserIsDeletedOrLocked(res) // Check Rate Limiting val resultWithRateLimiting: Future[(Box[User], Option[CallContext])] = AfterApiAuth.checkRateLimiting(userIsLockedOrDeleted) + // User init actions + val resultWithUserInitActions: Future[(Box[User], Option[CallContext])] = AfterApiAuth.userApiLogonInitAction(resultWithRateLimiting) // Update Call Context - resultWithRateLimiting map { + resultWithUserInitActions map { x => (x._1, ApiSession.updateCallContext(Spelling(spelling), x._2)) } map { x => (x._1, x._2.map(_.copy(implementedInVersion = implementedInVersion))) diff --git a/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala b/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala index 50cba999c..0319eff46 100644 --- a/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala +++ b/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala @@ -5,15 +5,52 @@ import java.util.Date import code.api.util.ErrorMessages.{UserIsDeleted, UsernameHasBeenLocked} import code.api.util.RateLimitingJson.CallLimit import code.loginattempts.LoginAttempt +import code.model.dataAccess.AuthUser import code.ratelimiting.{RateLimiting, RateLimitingDI} +import code.util.Helper.MdcLoggable import com.openbankproject.commons.model.User import net.liftweb.common.{Box, Empty, Failure, Full} import com.openbankproject.commons.ExecutionContext.Implicits.global +import net.liftweb.mapper.By import scala.concurrent.Future -object AfterApiAuth { +object AfterApiAuth extends MdcLoggable{ + /** + * This function is used to execute actions after an user is authenticated via GUI + * Types of authentication: GUI logon(OpenID Connect and OAuth1.0a) + * @param user the authenticated user + */ + def userGuiLogonInitAction(user: Box[AuthUser]) = { + user.map { u => // Init actions + logger.info("AfterApiAuth.userGuiLogonInitAction started successfully") + + } match { + case Full(_) => logger.warn("AfterApiAuth.userGuiLogonInitAction completed successfully") + case userInitActionFailure => logger.warn("AfterApiAuth.userGuiLogonInitAction: " + userInitActionFailure) + } + } + /** + * This function is used to execute actions after an user is authenticated via API + * Types of authentication: Direct Login, OpenID Connect, OAuth1.0a, Direct Login, DAuth and Gateway Login + */ + def userApiLogonInitAction(result: Future[(Box[User], Option[CallContext])]): Future[(Box[User], Option[CallContext])] = { + logger.info("AfterApiAuth.userApiLogonInitAction started successfully") + for { + (user: Box[User], cc) <- result + } yield { + user match { + case Full(u) => // There is a user. Apply init actions + val authUser: Box[AuthUser] = AuthUser.find(By(AuthUser.user, u.userPrimaryKey.value)) + userGuiLogonInitAction(authUser) + (user, cc) + case userInitActionFailure => // There is no user. Just forward the result. + logger.warn("AfterApiAuth.userApiLogonInitAction: " + userInitActionFailure) + (user, cc) + } + } + } def checkUserIsDeletedOrLocked(res: Future[(Box[User], Option[CallContext])]): Future[(Box[User], Option[CallContext])] = { for { (user: Box[User], cc) <- res diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index d888ab655..3a57a27c2 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -996,6 +996,8 @@ def restoreSomeSessions(): Unit = { // Reset any bad attempt LoginAttempt.resetBadLoginAttempts(usernameFromGui) val preLoginState = capturePreLoginState() + // User init actions + AfterApiAuth.userGuiLogonInitAction(Full(user)) logger.info("login redirect: " + loginRedirect.get) val redirect = redirectUri() checkInternalRedirectAndLogUseIn(preLoginState, redirect, user) @@ -1021,6 +1023,8 @@ def restoreSomeSessions(): Unit = { //This method is used for connector = kafka* || obpjvm* //It will update the views and createAccountHolder .... registeredUserHelper(user.username.get) + // User init actions + AfterApiAuth.userGuiLogonInitAction(Full(user)) checkInternalRedirectAndLogUseIn(preLoginState, redirect, user) // If user cannot be found locally, try to authenticate user via connector @@ -1034,6 +1038,8 @@ def restoreSomeSessions(): Unit = { externalUserHelper(usernameFromGui, passwordFromGui) match { case Full(user: AuthUser) => LoginAttempt.resetBadLoginAttempts(usernameFromGui) + // User init actions + AfterApiAuth.userGuiLogonInitAction(Full(user)) checkInternalRedirectAndLogUseIn(preLoginState, redirect, user) case _ => LoginAttempt.incrementBadLoginAttempts(username.get)