Skip to content

Commit

Permalink
fix: Ask timeouts with GetUserADM (DEV-1443) (#2267)
Browse files Browse the repository at this point in the history
  • Loading branch information
irinaschubert committed Oct 25, 2022
1 parent 41d5315 commit 3f77b6e
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -155,7 +155,7 @@ stack-down: ## stops the dsp-stack.
@docker compose -f docker-compose.yml down

.PHONY: stack-down-delete-volumes
stack-down-delete-volumes: clean-local-tmp clean-sipi-projects clean-sipi-tmp ## stops the dsp-stack and deletes any created volumes (deletes the database!).
stack-down-delete-volumes: clean-local-tmp clean-sipi-tmp ## stops the dsp-stack and deletes any created volumes (deletes the database!).
@docker compose -f docker-compose.yml down --volumes

.PHONY: stack-config
Expand Down
4 changes: 2 additions & 2 deletions dsp-api-main/src/main/scala/dsp/api/main/MainApp.scala
Expand Up @@ -13,6 +13,6 @@ object MainApp extends ZIOAppDefault {
// _ <- printLine(42).orDie
} yield ()

val mainApp: ZIO[Any, Nothing, Unit] = effect.provide(SchemaRepoLive.layer)
def run: ZIO[Any, Nothing, Unit] = mainApp
val mainApp: UIO[Unit] = effect.provide(SchemaRepoLive.layer)
def run: UIO[Unit] = mainApp
}
14 changes: 7 additions & 7 deletions webapi/src/main/scala/org/knora/webapi/core/AppServer.scala
Expand Up @@ -38,7 +38,7 @@ final case class AppServer(
/**
* Checks if the TriplestoreService is running and the repository is properly initialized.
*/
private val checkTriplestoreService: ZIO[Any, Nothing, Unit] =
private val checkTriplestoreService: UIO[Unit] =
for {
_ <- state.set(AppState.WaitingForTriplestore)
status <- ts.checkTriplestore().map(_.triplestoreStatus)
Expand All @@ -55,7 +55,7 @@ final case class AppServer(
*
* @param requiresRepository If `true`, calls the RepositoryUpdater to initiate the repository, otherwise returns ()
*/
private def upgradeRepository(requiresRepository: Boolean): ZIO[Any, Nothing, Unit] =
private def upgradeRepository(requiresRepository: Boolean): UIO[Unit] =
for {
_ <- state.set(AppState.UpdatingRepository)
_ <- ru.maybeUpgradeRepository.flatMap(response => ZIO.logInfo(response.message)).when(requiresRepository)
Expand All @@ -65,7 +65,7 @@ final case class AppServer(
/**
* Initiates building of all caches
*/
private val buildAllCaches: ZIO[Any, Nothing, Unit] =
private val buildAllCaches: UIO[Unit] =
for {
_ <- state.set(AppState.CreatingCaches)
_ <- ZIO.attempt {
Expand All @@ -80,7 +80,7 @@ final case class AppServer(
*
* @param requiresRepository If `true`, calls the AppRouter to populate the ontology caches, otherwise returns ()
*/
private def populateOntologyCaches(requiresRepository: Boolean): ZIO[Any, Nothing, Unit] =
private def populateOntologyCaches(requiresRepository: Boolean): UIO[Unit] =
for {
_ <- state.set(AppState.LoadingOntologies)
_ <- ar.populateOntologyCaches.when(requiresRepository)
Expand All @@ -92,7 +92,7 @@ final case class AppServer(
*
* @param requiresIIIFService If `true`, checks the status of the IIIFService instance, otherwise returns ()
*/
private def checkIIIFService(requiresIIIFService: Boolean): ZIO[Any, Nothing, Unit] =
private def checkIIIFService(requiresIIIFService: Boolean): UIO[Unit] =
for {
_ <- state.set(AppState.WaitingForIIIFService)
_ <- iiifs
Expand All @@ -110,7 +110,7 @@ final case class AppServer(
/**
* Checks if the Cache service is running
*/
private val checkCacheService: ZIO[Any, Nothing, Unit] =
private val checkCacheService: UIO[Unit] =
for {
_ <- state.set(AppState.WaitingForCacheService)
_ <- cs.getStatus.flatMap {
Expand All @@ -132,7 +132,7 @@ final case class AppServer(
def start(
requiresAdditionalRepositoryChecks: Boolean,
requiresIIIFService: Boolean
): ZIO[Any, Nothing, Unit] =
): UIO[Unit] =
for {
_ <- ZIO.logInfo("=> Startup checks initiated")
_ <- checkTriplestoreService
Expand Down
Expand Up @@ -990,7 +990,6 @@ class SearchResponderV2(responderData: ResponderData) extends ResponderWithStand
* @param limitToProject limit search to given project.
* @param limitToResourceClass limit search to given resource class.
* @param targetSchema the schema of the response.
*
* @param requestingUser the the client making the request.
* @return a [[ReadResourcesSequenceV2]] representing the resources that have been found.
*/
Expand Down
56 changes: 40 additions & 16 deletions webapi/src/main/scala/org/knora/webapi/routing/Authenticator.scala
Expand Up @@ -15,7 +15,6 @@ import akka.http.scaladsl.server.RequestContext
import akka.http.scaladsl.util.FastFuture
import akka.pattern._
import akka.util.ByteString
import akka.util.Timeout
import com.typesafe.scalalogging.Logger
import org.apache.commons.codec.binary.Base32
import org.slf4j.LoggerFactory
Expand Down Expand Up @@ -70,8 +69,10 @@ trait Authenticator extends InstrumentationSupport {
* with the generated session id for the client to save.
*
* @param requestContext a [[RequestContext]] containing the http request
*
* @param appConfig the application's configuration.
* @param system the current [[ActorSystem]]
* @param appActor a reference to the application actor
* @param executionContext the current execution context
* @return a [[HttpResponse]] containing either a failure message or a message with a cookie header containing
* the generated session id.
*/
Expand Down Expand Up @@ -128,8 +129,10 @@ trait Authenticator extends InstrumentationSupport {
* Checks if the provided credentials are valid, and if so returns a JWT token for the client to save.
*
* @param credentials the user supplied [[KnoraPasswordCredentialsV2]] containing the user's login information.
*
* @param appConfig the application's configuration.
* @param system the current [[ActorSystem]]
* @param appActor a reference to the application actor
* @param executionContext the current execution context
* @return a [[HttpResponse]] containing either a failure message or a message with a cookie header containing
* the generated session id.
*/
Expand Down Expand Up @@ -184,6 +187,15 @@ trait Authenticator extends InstrumentationSupport {
} yield httpResponse
}

/**
* Returns a simple login form for testing purposes
*
* @param requestContext a [[RequestContext]] containing the http request
* @param appConfig the application's configuration.
* @param system the current [[ActorSystem]]
* @param executionContext the current execution context
* @return a [[HttpResponse]] with an html login form
*/
def presentLoginFormV2(
requestContext: RequestContext,
appConfig: AppConfig
Expand Down Expand Up @@ -239,9 +251,11 @@ trait Authenticator extends InstrumentationSupport {
* generated.
*
* @param requestContext a [[RequestContext]] containing the http request
*
* @param appConfig the application's configuration.
* @param system the current [[ActorSystem]]
* @return a [[RequestContext]]
* @param appActor a reference to the application actor
* @param executionContext the current execution context
* @return a [[HttpResponse]]
*/
def doAuthenticateV1(requestContext: RequestContext, appConfig: AppConfig)(implicit
system: ActorSystem,
Expand Down Expand Up @@ -278,7 +292,10 @@ trait Authenticator extends InstrumentationSupport {
* Checks if the credentials provided in [[RequestContext]] are valid.
*
* @param requestContext a [[RequestContext]] containing the http request
* @param appConfig the application's configuration.
* @param system the current [[ActorSystem]]
* @param appActor a reference to the application actor
* @param executionContext the current execution context
* @return a [[HttpResponse]]
*/
def doAuthenticateV2(requestContext: RequestContext, appConfig: AppConfig)(implicit
Expand Down Expand Up @@ -403,9 +420,11 @@ trait Authenticator extends InstrumentationSupport {
* corresponding error is returned.
*
* @param requestContext a [[RequestContext]] containing the http request
*
* @param appConfig the application's configuration.
* @param system the current [[ActorSystem]]
* @return a [[UserProfileV1]]
* @param appActor a reference to the application actor
* @param executionContext the current execution context
* @return a [[UserADM]]
*/
def getUserADM(requestContext: RequestContext, appConfig: AppConfig)(implicit
system: ActorSystem,
Expand Down Expand Up @@ -450,7 +469,6 @@ object Authenticator extends InstrumentationSupport {
val AUTHENTICATION_INVALIDATION_CACHE_NAME = "authenticationInvalidationCache"

val sessionStore: scala.collection.mutable.Map[String, UserADM] = scala.collection.mutable.Map()
implicit val timeout: Timeout = Duration(5, SECONDS)
val log: Logger = Logger(LoggerFactory.getLogger(this.getClass))

private implicit val stringFormatter: StringFormatter = StringFormatter.getGeneralInstance
Expand All @@ -464,6 +482,8 @@ object Authenticator extends InstrumentationSupport {
* @param credentials the user supplied and extracted credentials.
* @param appConfig the application's configuration
* @param system the current [[ActorSystem]]
* @param appActor a reference to the application actor
* @param executionContext the current execution context
* @return true if the credentials are valid. If the credentials are invalid, then the corresponding exception
* will be thrown.
* @throws BadCredentialsException when no credentials are supplied; when user is not active;
Expand Down Expand Up @@ -535,7 +555,8 @@ object Authenticator extends InstrumentationSupport {
* Tries to extract the credentials from the requestContext (parameters, auth headers, token)
*
* @param requestContext a [[RequestContext]] containing the http request
* @return [[KnoraCredentialsV2]].
* @param appConfig the application's configuration.
* @return an optional [[KnoraCredentialsV2]].
*/
private def extractCredentialsV2(
requestContext: RequestContext,
Expand Down Expand Up @@ -563,7 +584,7 @@ object Authenticator extends InstrumentationSupport {
* Tries to extract credentials supplied as URL parameters.
*
* @param requestContext the HTTP request context.
* @return [[KnoraCredentialsV2]].
* @return an optional [[KnoraCredentialsV2]].
*/
private def extractCredentialsFromParametersV2(requestContext: RequestContext): Option[KnoraCredentialsV2] = {
// extract email/password from parameters
Expand Down Expand Up @@ -704,7 +725,10 @@ object Authenticator extends InstrumentationSupport {
* with authenticated credentials.
*
* @param credentials the user supplied credentials.
*
* @param appConfig the application's configuration.
* @param system the current [[ActorSystem]]
* @param appActor a reference to the application actor
* @param executionContext the current execution context
* @return a [[UserADM]]
* @throws AuthenticationException when the IRI can not be found inside the token, which is probably a bug.
*/
Expand Down Expand Up @@ -770,17 +794,15 @@ object Authenticator extends InstrumentationSupport {
* Tries to get a [[UserADM]].
*
* @param identifier the IRI, email, or username of the user to be queried
*
* @param system the current akka actor system
* @param timeout the timeout of the query
* @param appActor a reference to the application actor
* @param executionContext the current execution context
* @return a [[UserADM]]
* @throws BadCredentialsException when either the supplied email is empty or no user with such an email could be found.
*/
private def getUserByIdentifier(identifier: UserIdentifierADM)(implicit
system: ActorSystem,
appActor: ActorRef,
timeout: Timeout,
executionContext: ExecutionContext
): Future[UserADM] = tracedFuture("authenticator-get-user-by-identifier") {
for {
Expand All @@ -792,7 +814,7 @@ object Authenticator extends InstrumentationSupport {
userInformationTypeADM = UserInformationTypeADM.Full,
requestingUser = KnoraSystemInstances.Users.SystemUser
)
)
)(Duration(100, SECONDS))
.mapTo[Option[UserADM]]

user = maybeUserADM match {
Expand All @@ -812,6 +834,7 @@ object Authenticator extends InstrumentationSupport {
* This also needs to be changed in all the places that base32 is used to calculate the cookie name, e.g., sipi.
*
* @param appConfig the application's configuration.
* @return the calculated cookie name as [[String]]
*/
def calculateCookieName(appConfig: AppConfig): String = {
//
Expand Down Expand Up @@ -920,7 +943,7 @@ object JWTHelper {
* @param secret the secret used to encode the token.
* @param contentName the name of the content field to be extracted.
* @param issuer the principal that issued the JWT.
* @return the string value of the specified content field.
* @return the [[String]] value of the specified content field.
*/
def extractContentFromToken(token: String, secret: String, contentName: String, issuer: String): Option[String] =
decodeToken(token, secret, issuer) match {
Expand All @@ -938,6 +961,7 @@ object JWTHelper {
*
* @param token the token to be decoded.
* @param secret the secret used to encode the token.
* @param issuer the principal that issued the JWT.
* @return the token's header and claim, or `None` if the token is invalid.
*/
private def decodeToken(token: String, secret: String, issuer: String): Option[(JwtHeader, JwtClaim)] = {
Expand Down
Expand Up @@ -23,7 +23,7 @@ import org.knora.webapi.util.LogAspect
*/
trait HealthCheck {

protected def healthCheck(state: State): ZIO[Any, Nothing, HttpResponse] =
protected def healthCheck(state: State): UIO[HttpResponse] =
for {
_ <- ZIO.logInfo("get application state")
state <- state.get
Expand Down
Expand Up @@ -76,7 +76,7 @@ case class CacheServiceInMemImpl(
* @param id the user's IRI.
* @return an optional [[UserADM]].
*/
def getUserByIri(id: String): ZIO[Any, Nothing, Option[UserADM]] =
def getUserByIri(id: String): UIO[Option[UserADM]] =
users.get(id).commit

/**
Expand All @@ -85,7 +85,7 @@ case class CacheServiceInMemImpl(
* @param usernameOrEmail of the user.
* @return an optional [[UserADM]].
*/
def getUserByUsernameOrEmail(usernameOrEmail: String): ZIO[Any, Nothing, Option[UserADM]] =
def getUserByUsernameOrEmail(usernameOrEmail: String): UIO[Option[UserADM]] =
(for {
iri <- lut.get(usernameOrEmail).some
user <- users.get(iri).some
Expand Down
Expand Up @@ -27,7 +27,7 @@ trait IIIFServiceManager {
* incoming Akka messages to calls to ZIO based implementations. Each ZIO response
* is then translated back to Akka through [[ActorUtil.zio2Message]].
*/
def receive(message: IIIFRequest): ZIO[Any, Nothing, Any]
def receive(message: IIIFRequest): UIO[Any]

}

Expand Down
Expand Up @@ -147,7 +147,7 @@ case class IIIFServiceSipiImpl(
)
)

def deleteUrl(token: String): ZIO[Any, Nothing, String] =
def deleteUrl(token: String): UIO[String] =
ZIO.succeed(
s"${appConfig.sipi.internalBaseUrl}/${appConfig.sipi.deleteTempFileRoute}/${deleteTemporaryFileRequestV2.internalFilename}?token=$token"
)
Expand Down
Expand Up @@ -41,7 +41,7 @@ import org.knora.webapi.store.triplestore.upgrade.RepositoryUpdater
*/
@accessible
trait TriplestoreServiceManager {
def receive(message: TriplestoreRequest): ZIO[Any, Nothing, Any]
def receive(message: TriplestoreRequest): UIO[Any]
}

object TriplestoreServiceManager {
Expand Down
Expand Up @@ -44,7 +44,6 @@ class AuthenticatorSpec extends CoreSpec with ImplicitSender with PrivateMethodT
UserIdentifierADM(maybeEmail = Some(AuthenticatorSpec.rootUserEmail)),
system,
appActor,
timeout,
executionContext
)
resF map { res =>
Expand All @@ -57,7 +56,6 @@ class AuthenticatorSpec extends CoreSpec with ImplicitSender with PrivateMethodT
UserIdentifierADM(maybeEmail = Some("wronguser@example.com")),
system,
appActor,
timeout,
executionContext
)
resF map { _ =>
Expand All @@ -71,7 +69,6 @@ class AuthenticatorSpec extends CoreSpec with ImplicitSender with PrivateMethodT
UserIdentifierADM(),
system,
appActor,
timeout,
executionContext
)
}
Expand Down

0 comments on commit 3f77b6e

Please sign in to comment.