Skip to content

Commit

Permalink
refactor!: Remove zio admin/projects http routes on port 5555 (DEV-2809
Browse files Browse the repository at this point in the history
…) (#2879)
  • Loading branch information
seakayone authored Oct 19, 2023
1 parent 20f6560 commit e1b6eeb
Show file tree
Hide file tree
Showing 30 changed files with 132 additions and 1,629 deletions.
66 changes: 44 additions & 22 deletions integration/src/test/scala/org/knora/sipi/SipiIT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder
import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder.newRequestPattern
import zio._
import zio.http._
import zio.http.model.Status
import zio.json.DecoderOps
import zio.json.ast.Json
import zio.test._
Expand Down Expand Up @@ -41,8 +40,12 @@ object SipiIT extends ZIOSpecDefault {
SipiTestContainer.copyFileToImageFolderInContainer(prefix, _)
)

private def getWithoutAuthorization(path: String) =
SipiTestContainer.resolveUrl(path).map(Request.get).flatMap(Client.request(_))
private def getWithoutAuthorization(path: Path) =
SipiTestContainer
.resolveUrl(path)
.tap(url => Console.printLine(s"SIPI URL resolved: GET $url"))
.map(Request.get)
.flatMap(Client.request(_))

private val getToken = JwtService
.createJwt(SystemUser)
Expand All @@ -63,12 +66,22 @@ object SipiIT extends ZIOSpecDefault {
_ <- MockDspApiServer.resetAndAllowWithPermissionCode(prefix, imageTestfile, 2)
response <-
SipiTestContainer
.resolveUrl(s"/$prefix/$imageTestfile/file")
.resolveUrl(Root / prefix / imageTestfile / "file")
.map { url =>
Request
.get(url)
.withCookie(
s"KnoraAuthenticationGAXDALRQFYYDUMZTGMZQ9999aSecondCookie=anotherValueShouldBeIgnored; KnoraAuthenticationGAXDALRQFYYDUMZTGMZQ9999=$jwt"
.addHeaders(
Headers(
Header.Cookie(
NonEmptyChunk(
Cookie.Request(
s"KnoraAuthenticationGAXDALRQFYYDUMZTGMZQ9999aSecondCookie",
"anotherValueShouldBeIgnored"
),
Cookie.Request("KnoraAuthenticationGAXDALRQFYYDUMZTGMZQ9999", jwt)
)
)
)
)
}
.flatMap(Client.request(_))
Expand All @@ -87,8 +100,16 @@ object SipiIT extends ZIOSpecDefault {
_ <- MockDspApiServer.resetAndAllowWithPermissionCode(prefix, imageTestfile, 2)
response <-
SipiTestContainer
.resolveUrl(s"/$prefix/$imageTestfile/file")
.map(url => Request.get(url).withCookie(s"KnoraAuthenticationGAXDALRQFYYDUMZTGMZQ9999=$jwt"))
.resolveUrl(Root / prefix / imageTestfile / "file")
.map(url =>
Request
.get(url)
.addHeaders(
Headers(
Header.Cookie(NonEmptyChunk(Cookie.Request("KnoraAuthenticationGAXDALRQFYYDUMZTGMZQ9999", jwt)))
)
)
)
.flatMap(Client.request(_))
requestToDspApiContainsJwt <- MockDspApiServer.verifyAuthBearerTokenReceived(jwt)
} yield assertTrue(response.status == Status.Ok, requestToDspApiContainsJwt)
Expand All @@ -104,10 +125,10 @@ object SipiIT extends ZIOSpecDefault {
"when getting the file, " +
"then Sipi responds with Ok"
) {
def expectedJson(port: Int) =
def expectedJson(port: Int, host: String) =
s"""{
| "@context":"http://sipi.io/api/file/3/context.json",
| "id":"http://localhost:$port/0001/FGiLaT4zzuV-CqwbEDFAFeS.jp2",
| "id":"http://$host:$port/0001/FGiLaT4zzuV-CqwbEDFAFeS.jp2",
| "checksumOriginal":"fb252a4fb3d90ce4ebc7e123d54a4112398a7994541b11aab5e4230eac01a61c",
| "checksumDerivative":"0ce405c9b183fb0d0a9998e9a49e39c93b699e0f8e2a9ac3496c349e5cea09cc",
| "width":250,
Expand All @@ -119,9 +140,9 @@ object SipiIT extends ZIOSpecDefault {
for {
_ <- MockDspApiServer.resetAndAllowWithPermissionCode(prefix, imageTestfile, permissionCode = 2)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/knora.json")
response <- getWithoutAuthorization(Root / prefix / imageTestfile / "knora.json")
json <- response.body.asString.map(_.fromJson[Json])
expected <- SipiTestContainer.port.map(expectedJson)
expected <- SipiTestContainer.portAndHost.map { case (port, host) => expectedJson(port, host) }
} yield assertTrue(
response.status == Status.Ok,
json == expected
Expand All @@ -138,7 +159,7 @@ object SipiIT extends ZIOSpecDefault {
test("When getting the file, then Sipi responds with Not Found") {
for {
server <- MockDspApiServer.resetAndGetWireMockServer
response <- getWithoutAuthorization(s"/$prefix/doesnotexist.jp2/file")
response <- getWithoutAuthorization(Root / prefix / "doesnotexist.jp2" / "file")
} yield assertTrue(response.status == Status.NotFound, verifyNoInteractionWith(server))
}
),
Expand All @@ -153,7 +174,7 @@ object SipiIT extends ZIOSpecDefault {
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/file")
response <- getWithoutAuthorization(Root / prefix / imageTestfile / "file")
} yield assertTrue(
response.status == Status.Ok,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -169,7 +190,7 @@ object SipiIT extends ZIOSpecDefault {
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/file")
response <- getWithoutAuthorization(Root / prefix / imageTestfile / "file")
} yield assertTrue(
response.status == Status.Unauthorized,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -184,7 +205,7 @@ object SipiIT extends ZIOSpecDefault {
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 404)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/file")
response <- getWithoutAuthorization(Root / prefix / imageTestfile / "file")
} yield assertTrue(
response.status == Status.NotFound,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -202,8 +223,9 @@ object SipiIT extends ZIOSpecDefault {
"then Sipi responds with Not Found"
) {
for {
server <- MockDspApiServer.resetAndGetWireMockServer
response <- getWithoutAuthorization(s"/$prefix/doesnotexist.jp2/full/max/0/default.jp2")
server <- MockDspApiServer.resetAndGetWireMockServer
response <-
getWithoutAuthorization(Root / prefix / "doesnotexist.jp2" / "full" / "max" / "0" / "default.jp2")
} yield assertTrue(response.status == Status.NotFound, verifyNoInteractionWith(server))
}
),
Expand All @@ -218,7 +240,7 @@ object SipiIT extends ZIOSpecDefault {
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/full/max/0/default.jp2")
response <- getWithoutAuthorization(Root / prefix / imageTestfile / "full/max/0/default.jp2")
} yield assertTrue(
response.status == Status.Ok,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -234,7 +256,7 @@ object SipiIT extends ZIOSpecDefault {
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/full/max/0/default.jp2")
response <- getWithoutAuthorization(Root / prefix / imageTestfile / "full/max/0/default.jp2")
} yield assertTrue(
response.status == Status.Unauthorized,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -249,7 +271,7 @@ object SipiIT extends ZIOSpecDefault {
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 404)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/full/max/0/default.jp2")
response <- getWithoutAuthorization(Root / prefix / imageTestfile / "full/max/0/default.jp2")
} yield assertTrue(
response.status == Status.NotFound,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -267,7 +289,7 @@ object SipiIT extends ZIOSpecDefault {
test("health check works") {
for {
server <- MockDspApiServer.resetAndGetWireMockServer
response <- getWithoutAuthorization("/server/test.html")
response <- getWithoutAuthorization(Root / "server" / "test.html")
} yield assertTrue(response.status.isSuccess, verifyNoInteractionWith(server))
}
)
Expand Down
8 changes: 3 additions & 5 deletions integration/src/test/scala/org/knora/webapi/E2ESpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,9 @@ abstract class E2ESpec
val appActor = router.ref

// needed by some tests
val appConfig = config
val routeData = KnoraRouteData(system, appActor, appConfig)
val baseApiUrl =
if (sys.props.get("key") == Some("zio")) "http://0.0.0.0:5555"
else appConfig.knoraApi.internalKnoraApiBaseUrl
val appConfig = config
val routeData = KnoraRouteData(system, appActor, appConfig)
val baseApiUrl = appConfig.knoraApi.internalKnoraApiBaseUrl

final override def beforeAll(): Unit =
/* Here we start our app and initialize the repository before each suit runs */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import zio._

import org.knora.webapi.config.AppConfig.AppConfigurations
import org.knora.webapi.config.AppConfigForTestContainers
import org.knora.webapi.http.middleware.AuthenticationMiddleware
import org.knora.webapi.messages.StringFormatter
import org.knora.webapi.messages.util._
import org.knora.webapi.messages.util.search.QueryTraverser
Expand All @@ -28,8 +27,6 @@ import org.knora.webapi.responders.v2.ontology.CardinalityHandlerLive
import org.knora.webapi.responders.v2.ontology.OntologyHelpers
import org.knora.webapi.responders.v2.ontology.OntologyHelpersLive
import org.knora.webapi.routing._
import org.knora.webapi.routing.admin.AuthenticatorService
import org.knora.webapi.routing.admin.ProjectsRouteZ
import org.knora.webapi.slice.admin.api._
import org.knora.webapi.slice.admin.api.service.MaintenanceRestService
import org.knora.webapi.slice.admin.api.service.ProjectADMRestService
Expand Down Expand Up @@ -135,9 +132,7 @@ object LayersTest {
AdminApiRoutes.layer,
ApiRoutes.layer,
AppRouter.layer,
AuthenticationMiddleware.layer,
AuthenticatorLive.layer,
AuthenticatorService.layer,
BaseEndpoints.layer,
CacheServiceInMemImpl.layer,
CacheServiceRequestMessageHandlerLive.layer,
Expand Down Expand Up @@ -180,7 +175,6 @@ object LayersTest {
ProjectsEndpoints.layer,
ProjectsEndpointsHandler.layer,
ProjectsResponderADMLive.layer,
ProjectsRouteZ.layer,
QueryTraverser.layer,
RepositoryUpdater.layer,
ResourceInfoRepo.layer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class ProjectsADME2EZioHttpSpec extends E2ESpec with ProjectsADMJsonProtocol {
)
)

s"The Projects Route ($baseApiUrl -> 'admin/projects')" when {
s"The Projects Route 'admin/projects'" when {
"used to query for project information" should {
"return all projects excluding built-in system projects" in {
val request = Get(baseApiUrl + s"/admin/projects") ~> addCredentials(BasicHttpCredentials(rootEmail, testPass))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ trait FusekiTestContainer extends GenericContainer[FusekiTestContainer] {

def baseUrl: URL = {
val urlString = s"http://$getHost:$getFirstMappedPort"
URL.fromString(urlString).getOrElse(throw new IllegalStateException(s"Invalid URL $urlString"))
URL.decode(urlString).getOrElse(throw new IllegalStateException(s"Invalid URL $urlString"))
}

def credentials: (String, String) = ("admin", FusekiTestContainer.adminPassword)
Expand All @@ -48,7 +48,7 @@ trait FusekiTestContainer extends GenericContainer[FusekiTestContainer] {
.map(_.map(line => line.replace("@REPOSITORY@", repositoryName)).mkString("\n"))
request = HttpRequest
.newBuilder()
.uri(baseUrl.setPath("/$/datasets").toJavaURI)
.uri(baseUrl.withPath("/$/datasets").toJavaURI)
.POST(BodyPublishers.ofString(fusekiConfig))
.header("Content-Type", "text/turtle; charset=utf-8")
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@ import org.testcontainers.containers.BindMode
import org.testcontainers.containers.GenericContainer
import org.testcontainers.utility.DockerImageName
import org.testcontainers.utility.MountableFile
import zio._
import zio.Task
import zio.UIO
import zio.URIO
import zio.ZIO
import zio.ZLayer
import zio.http
import zio.http.URL
import zio.nio.file.Path

import java.net.NetworkInterface
import java.net.UnknownHostException
import java.net.Inet6Address
import java.net.InetAddress
import java.nio.file.Paths
import scala.jdk.CollectionConverters._

import org.knora.webapi.http.version.BuildInfo

Expand All @@ -36,19 +40,36 @@ final case class SipiTestContainer(container: GenericContainer[Nothing]) {
)
}

def host: String = container.getHost
def port: Int = container.getFirstMappedPort
def sipiBaseUrl: URL = {
val port: Int = container.getFirstMappedPort

val host: String = SipiTestContainer.localHostAddress

val sipiBaseUrl: URL = {
val urlString = s"http://$host:$port"
URL.fromString(urlString).getOrElse(throw new IllegalStateException(s"Invalid URL $urlString"))
println(s"SIPI URL String: $urlString")
val url = URL.decode(urlString).getOrElse(throw new IllegalStateException(s"Invalid URL $urlString"))
println(s"SIPI URL: $url")
url
}
}

object SipiTestContainer {
def port: ZIO[SipiTestContainer, Nothing, Int] = ZIO.serviceWith[SipiTestContainer](_.port)

def resolveUrl(path: String): URIO[SipiTestContainer, URL] =
ZIO.serviceWith[SipiTestContainer](_.sipiBaseUrl.setPath(path))
val localHostAddress: String = {
val localhost = InetAddress.getLocalHost
if (localhost.isInstanceOf[Inet6Address]) {
s"[${localhost.getHostAddress}]"
} else {
localhost.getHostAddress
}
}

def port: ZIO[SipiTestContainer, Nothing, Int] = ZIO.serviceWith[SipiTestContainer](_.port)
def host: ZIO[SipiTestContainer, Nothing, String] = ZIO.serviceWith[SipiTestContainer](_.host)
def portAndHost: ZIO[SipiTestContainer, Nothing, (Int, String)] = port <*> host

def resolveUrl(path: http.Path): URIO[SipiTestContainer, URL] =
ZIO.serviceWith[SipiTestContainer](_.sipiBaseUrl.withPath(path))

def copyFileToImageFolderInContainer(prefix: String, filename: String): ZIO[SipiTestContainer, Throwable, Unit] =
ZIO.serviceWithZIO[SipiTestContainer](_.copyFileToImageFolderInContainer(prefix, filename))
Expand All @@ -60,13 +81,8 @@ object SipiTestContainer {
* A functional effect that initiates a Sipi Testcontainer
*/
val acquire: UIO[GenericContainer[Nothing]] = ZIO.attemptBlocking {
// get local IP address, which we need for SIPI
val localIpAddress: String = NetworkInterface.getNetworkInterfaces.asScala.toSeq
.filter(!_.isLoopback)
.flatMap(_.getInetAddresses.asScala.toSeq.filter(_.getAddress.length == 4).map(_.toString))
.headOption
.getOrElse(throw new UnknownHostException("No suitable network interface found"))

// Uncomment the following line to use the latest version of Sipi for local development:
// val sipiImageName: DockerImageName = DockerImageName.parse(s"daschswiss/knora-sipi:latest")
val sipiImageName: DockerImageName = DockerImageName.parse(s"daschswiss/knora-sipi:${BuildInfo.version}")
val sipiContainer = new GenericContainer(sipiImageName)
sipiContainer.withExposedPorts(1024)
Expand All @@ -75,7 +91,7 @@ object SipiTestContainer {
sipiContainer.withEnv("SIPI_EXTERNAL_PROTOCOL", "http")
sipiContainer.withEnv("SIPI_EXTERNAL_HOSTNAME", "0.0.0.0")
sipiContainer.withEnv("SIPI_EXTERNAL_PORT", "1024")
sipiContainer.withEnv("SIPI_WEBAPI_HOSTNAME", localIpAddress)
sipiContainer.withEnv("SIPI_WEBAPI_HOSTNAME", SipiTestContainer.localHostAddress)
sipiContainer.withEnv("SIPI_WEBAPI_PORT", "3333")
sipiContainer.withEnv("CLEAN_TMP_DIR_USER", "clean_tmp_dir_user")
sipiContainer.withEnv("CLEAN_TMP_DIR_PW", "clean_tmp_dir_pw")
Expand Down
7 changes: 1 addition & 6 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ object Dependencies {
val JenaVersion = "4.8.0"

val ZioConfigVersion = "3.0.7"
val ZioHttpVersionOld = "2.0.0-RC11"
val ZioHttpVersion = "0.0.3"
val ZioLoggingVersion = "2.1.14"
val ZioNioVersion = "2.0.2"
val ZioMetricsConnectorsVersion = "2.2.0"
Expand All @@ -36,8 +34,6 @@ object Dependencies {
val zioConfig = "dev.zio" %% "zio-config" % ZioConfigVersion
val zioConfigMagnolia = "dev.zio" %% "zio-config-magnolia" % ZioConfigVersion
val zioConfigTypesafe = "dev.zio" %% "zio-config-typesafe" % ZioConfigVersion
val zioHttpOld = "io.d11" %% "zhttp" % ZioHttpVersionOld
val zioHttp = "dev.zio" %% "zio-http" % ZioHttpVersion
val zioJson = "dev.zio" %% "zio-json" % "0.6.2"
val zioLogging = "dev.zio" %% "zio-logging" % ZioLoggingVersion
val zioLoggingSlf4jBridge = "dev.zio" %% "zio-logging-slf4j2-bridge" % ZioLoggingVersion
Expand Down Expand Up @@ -129,7 +125,7 @@ object Dependencies {

val tapir = Seq(
"com.softwaremill.sttp.tapir" %% "tapir-pekko-http-server" % tapirVersion,
// "com.softwaremill.sttp.tapir" %% "tapir-zio-http-server" % tapirVersion,
"com.softwaremill.sttp.tapir" %% "tapir-zio-http-server" % tapirVersion,
"com.softwaremill.sttp.tapir" %% "tapir-json-zio" % tapirVersion,
"com.softwaremill.sttp.tapir" %% "tapir-json-spray" % tapirVersion,
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-bundle" % tapirVersion,
Expand Down Expand Up @@ -189,7 +185,6 @@ object Dependencies {
zioConfig,
zioConfigMagnolia,
zioConfigTypesafe,
zioHttp,
zioJson,
zioLogging,
zioLoggingSlf4jBridge,
Expand Down
Loading

0 comments on commit e1b6eeb

Please sign in to comment.