Skip to content

Commit

Permalink
test: Add sipi auth tests for knora.json (NO-Ticket) (#2711)
Browse files Browse the repository at this point in the history
  • Loading branch information
seakayone committed Jun 20, 2023
1 parent 64e72be commit 85a30a5
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 81 deletions.
Binary file removed webapi/src/it/resources/sipi/testfiles/250x250.png
Binary file not shown.
@@ -0,0 +1,7 @@
{
"originalInternalFilename": "FGiLaT4zzuV-CqwbEDFAFeS.jp2.orig",
"checksumDerivative": "0ce405c9b183fb0d0a9998e9a49e39c93b699e0f8e2a9ac3496c349e5cea09cc",
"internalFilename": "FGiLaT4zzuV-CqwbEDFAFeS.jp2",
"checksumOriginal": "fb252a4fb3d90ce4ebc7e123d54a4112398a7994541b11aab5e4230eac01a61c",
"originalFilename": "250x250.jp2"
}
Binary file not shown.
199 changes: 128 additions & 71 deletions webapi/src/it/scala/org/knora/sipi/SipiIT.scala
Expand Up @@ -17,6 +17,9 @@ import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder
import zio._
import zio.http._
import zio.http.model.Status
import zio.json.DecoderOps
import zio.json.EncoderOps
import zio.json.ast.Json
import zio.test._
import scala.util.Failure
import scala.util.Success
Expand All @@ -29,70 +32,113 @@ import org.knora.webapi.testcontainers.SipiTestContainer

object SipiIT extends ZIOSpecDefault {

private val identifierTestFile = "250x250.jp2"
private val prefix = "0001"
private def copyTestImageToSipi = SipiTestContainer.copyImageToContainer(prefix, identifierTestFile)
private def sendGetRequestToSipi(path: String) =
private val imageTestfile = "FGiLaT4zzuV-CqwbEDFAFeS.jp2"
private val infoTestfile = "FGiLaT4zzuV-CqwbEDFAFeS.info"
private val origTestfile = "FGiLaT4zzuV-CqwbEDFAFeS.jp2.orig"
private val prefix = "0001"
private def copyTestFilesToSipi = ZIO.foreach(List(imageTestfile, infoTestfile, origTestfile))(
SipiTestContainer.copyFileToImageFolderInContainer(prefix, _)
)

private def getWithoutAuthorization(path: String) =
SipiTestContainer.resolveUrl(path).map(Request.get).flatMap(Client.request(_))

private val knoraJsonEndpointSuite =
suite("Endpoint /{prefix}/{identifier}/knora.json")(
suite("Given the user is unauthorized")(
suite("And given a .info file exists in Sipi")(
test(
"And given dsp-api returns 2='full view permissions on file', " +
"when getting the file, " +
"then Sipi responds with Ok"
) {
def expectedJson(port: Int) =
s"""{
| "@context":"http://sipi.io/api/file/3/context.json",
| "id":"http://localhost:$port/0001/FGiLaT4zzuV-CqwbEDFAFeS.jp2",
| "checksumOriginal":"fb252a4fb3d90ce4ebc7e123d54a4112398a7994541b11aab5e4230eac01a61c",
| "checksumDerivative":"0ce405c9b183fb0d0a9998e9a49e39c93b699e0f8e2a9ac3496c349e5cea09cc",
| "width":250,
| "height":250,
| "internalMimeType":"image/jp2",
| "originalMimeType":"image/jp2",
| "originalFilename":"250x250.jp2"
|}""".stripMargin.fromJson[Json]
for {
_ <- MockDspApiServer.resetAndAllowWithPermissionCode(prefix, imageTestfile, permissionCode = 2)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/knora.json")
json <- response.body.asString.map(_.fromJson[Json])
expected <- SipiTestContainer.port.map(expectedJson)
} yield assertTrue(
response.status == Status.Ok,
json == expected
)
}
)
)
)

private val fileEndpointSuite =
suite("Endpoint /{prefix}/{identifier}/file")(
suite("Given a file does not exist in Sipi")(
test("When getting the file, then Sipi responds with Not Found") {
for {
server <- MockDspApiServer.resetAndGetWireMockServer
response <- sendGetRequestToSipi(s"/$prefix/doesnotexist.jp2/file")
} yield assertTrue(response.status == Status.NotFound, verifyNoInteractionWith(server))
}
),
suite("Given a file exists in Sipi")(
test(
"And given dsp-api returns 2='full view permissions on file', " +
"when getting the file, " +
"then Sipi responds with Ok"
) {
val dspApiResponse = SipiFileInfoGetResponseADM(permissionCode = 2, restrictedViewSettings = None)
val dspApiPermissionPath = s"/admin/files/$prefix/$identifierTestFile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestImageToSipi
response <- sendGetRequestToSipi(s"/$prefix/$identifierTestFile/file")
} yield assertTrue(
response.status == Status.Ok,
verifySingleGetRequest(server, dspApiPermissionPath)
)
},
test(
"And given dsp-api returns 0='no view permission on file', " +
"when getting the file, " +
"then Sipi responds with Unauthorized"
) {
val dspApiResponse = SipiFileInfoGetResponseADM(permissionCode = 0, restrictedViewSettings = None)
val dspApiPermissionPath = s"/admin/files/$prefix/$identifierTestFile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestImageToSipi
response <- sendGetRequestToSipi(s"/$prefix/$identifierTestFile/file")
} yield assertTrue(
response.status == Status.Unauthorized,
verifySingleGetRequest(server, dspApiPermissionPath)
)
},
test(
"And given dsp-api does not know this file and returns Not Found, " +
"when getting the file, returns 2='full view permissions on file'" +
"then Sipi responds with Not Found"
) {
val dspApiPermissionPath = s"/admin/files/$prefix/$identifierTestFile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 404)
_ <- copyTestImageToSipi
response <- sendGetRequestToSipi(s"/$prefix/$identifierTestFile/file")
} yield assertTrue(
response.status == Status.NotFound,
verifySingleGetRequest(server, dspApiPermissionPath)
)
}
suite("Given the user is unauthorized")(
suite("Given a file does not exist in Sipi")(
test("When getting the file, then Sipi responds with Not Found") {
for {
server <- MockDspApiServer.resetAndGetWireMockServer
response <- getWithoutAuthorization(s"/$prefix/doesnotexist.jp2/file")
} yield assertTrue(response.status == Status.NotFound, verifyNoInteractionWith(server))
}
),
suite("Given an image exists in Sipi")(
test(
"And given dsp-api returns 2='full view permissions on file', " +
"when getting the file, " +
"then Sipi responds with Ok"
) {
val dspApiResponse = SipiFileInfoGetResponseADM(permissionCode = 2, restrictedViewSettings = None)
val dspApiPermissionPath = s"/admin/files/$prefix/$imageTestfile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/file")
} yield assertTrue(
response.status == Status.Ok,
verifySingleGetRequest(server, dspApiPermissionPath)
)
},
test(
"And given dsp-api returns 0='no view permission on file', " +
"when getting the file, " +
"then Sipi responds with Unauthorized"
) {
val dspApiResponse = SipiFileInfoGetResponseADM(permissionCode = 0, restrictedViewSettings = None)
val dspApiPermissionPath = s"/admin/files/$prefix/$imageTestfile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/file")
} yield assertTrue(
response.status == Status.Unauthorized,
verifySingleGetRequest(server, dspApiPermissionPath)
)
},
test(
"And given dsp-api does not know this file and returns Not Found, " +
"when getting the file, returns 2='full view permissions on file'" +
"then Sipi responds with Not Found"
) {
val dspApiPermissionPath = s"/admin/files/$prefix/$imageTestfile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 404)
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/file")
} yield assertTrue(
response.status == Status.NotFound,
verifySingleGetRequest(server, dspApiPermissionPath)
)
}
)
)
)

Expand All @@ -105,7 +151,7 @@ object SipiIT extends ZIOSpecDefault {
) {
for {
server <- MockDspApiServer.resetAndGetWireMockServer
response <- sendGetRequestToSipi(s"/$prefix/doesnotexist.jp2/full/max/0/default.jp2")
response <- getWithoutAuthorization(s"/$prefix/doesnotexist.jp2/full/max/0/default.jp2")
} yield assertTrue(response.status == Status.NotFound, verifyNoInteractionWith(server))
}
),
Expand All @@ -116,11 +162,11 @@ object SipiIT extends ZIOSpecDefault {
"Sipi responds with Ok"
) {
val dspApiResponse = SipiFileInfoGetResponseADM(permissionCode = 2, restrictedViewSettings = None)
val dspApiPermissionPath = s"/admin/files/$prefix/$identifierTestFile"
val dspApiPermissionPath = s"/admin/files/$prefix/$imageTestfile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestImageToSipi
response <- sendGetRequestToSipi(s"/$prefix/$identifierTestFile/full/max/0/default.jp2")
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/full/max/0/default.jp2")
} yield assertTrue(
response.status == Status.Ok,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -132,11 +178,11 @@ object SipiIT extends ZIOSpecDefault {
"Sipi responds with Unauthorized"
) {
val dspApiResponse = SipiFileInfoGetResponseADM(permissionCode = 0, restrictedViewSettings = None)
val dspApiPermissionPath = s"/admin/files/$prefix/$identifierTestFile"
val dspApiPermissionPath = s"/admin/files/$prefix/$imageTestfile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
_ <- copyTestImageToSipi
response <- sendGetRequestToSipi(s"/$prefix/$identifierTestFile/full/max/0/default.jp2")
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/full/max/0/default.jp2")
} yield assertTrue(
response.status == Status.Unauthorized,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -147,11 +193,11 @@ object SipiIT extends ZIOSpecDefault {
"when getting the file, " +
"Sipi responds with Not Found"
) {
val dspApiPermissionPath = s"/admin/files/$prefix/$identifierTestFile"
val dspApiPermissionPath = s"/admin/files/$prefix/$imageTestfile"
for {
server <- MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 404)
_ <- copyTestImageToSipi
response <- sendGetRequestToSipi(s"/$prefix/$identifierTestFile/full/max/0/default.jp2")
_ <- copyTestFilesToSipi
response <- getWithoutAuthorization(s"/$prefix/$imageTestfile/full/max/0/default.jp2")
} yield assertTrue(
response.status == Status.NotFound,
verifySingleGetRequest(server, dspApiPermissionPath)
Expand All @@ -162,12 +208,13 @@ object SipiIT extends ZIOSpecDefault {

override def spec: Spec[TestEnvironment with Scope, Any] =
suite("Sipi integration tests with mocked dsp-api")(
knoraJsonEndpointSuite,
fileEndpointSuite,
iiifEndpoint,
test("health check works") {
for {
server <- MockDspApiServer.resetAndGetWireMockServer
response <- sendGetRequestToSipi("/server/test.html")
response <- getWithoutAuthorization("/server/test.html")
} yield assertTrue(response.status.isSuccess, verifyNoInteractionWith(server))
}
)
Expand Down Expand Up @@ -203,6 +250,16 @@ object MockDspApiServer {
def resetAndStubGetResponse(url: String, status: Int, body: KnoraResponseADM): URIO[WireMockServer, WireMockServer] =
resetAndGetWireMockServer.tap(server => ZIO.succeed(stubGetJsonResponse(server, url, status, Some(body))))

def resetAndAllowWithPermissionCode(
prefix: String,
identifier: String,
permissionCode: Int
): URIO[WireMockServer, WireMockServer] = {
val dspApiResponse = SipiFileInfoGetResponseADM(permissionCode, restrictedViewSettings = None)
val dspApiPermissionPath = s"/admin/files/$prefix/$identifier"
MockDspApiServer.resetAndStubGetResponse(dspApiPermissionPath, 200, dspApiResponse)
}

private def stubGetJsonResponse(
server: WireMockServer,
url: String,
Expand Down
Expand Up @@ -11,6 +11,7 @@ import org.testcontainers.utility.DockerImageName
import org.testcontainers.utility.MountableFile
import zio._
import zio.http.URL
import zio.nio.file.Path
import java.net.NetworkInterface
import java.net.UnknownHostException
import java.nio.file.Paths
Expand All @@ -19,13 +20,18 @@ import scala.jdk.CollectionConverters._
import org.knora.webapi.http.version.BuildInfo

final case class SipiTestContainer(container: GenericContainer[Nothing]) {
def copyImageToContainer(prefix: String, filename: String): Task[Unit] = {
val seg01 = filename.substring(0, 2)
val seg02 = filename.substring(2, 4)
val target = s"/sipi/images/$prefix/$seg01/$seg02/$filename"
val file = MountableFile.forClasspathResource("sipi/testfiles/" + filename, 777)
ZIO.attemptBlocking(container.copyFileToContainer(file, target)) <* ZIO.logInfo(
s"copied $prefix/$filename to $target"
def copyFileToImageFolderInContainer(prefix: String, filename: String): Task[Unit] = {
val seg01 = filename.substring(0, 2).toLowerCase()
val seg02 = filename.substring(2, 4).toLowerCase()
val target = Path(s"/sipi/images/$prefix/$seg01/$seg02/$filename")
copyTestFileToContainer(filename, target)
}

def copyTestFileToContainer(file: String, target: Path): Task[Unit] = {
val resourceName = s"sipi/testfiles/$file"
val mountableFile = MountableFile.forClasspathResource(resourceName, 777)
ZIO.attemptBlockingIO(container.copyFileToContainer(mountableFile, target.toFile.toString)) <* ZIO.logInfo(
s"copied $resourceName to $target"
)
}

Expand All @@ -38,11 +44,16 @@ final case class SipiTestContainer(container: GenericContainer[Nothing]) {
}

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))

def copyImageToContainer(prefix: String, filename: String): ZIO[SipiTestContainer, Throwable, Unit] =
ZIO.serviceWithZIO[SipiTestContainer](_.copyImageToContainer(prefix, filename))
def copyFileToImageFolderInContainer(prefix: String, filename: String): ZIO[SipiTestContainer, Throwable, Unit] =
ZIO.serviceWithZIO[SipiTestContainer](_.copyFileToImageFolderInContainer(prefix, filename))

def copyTestFileToContainer(file: String, target: Path): ZIO[SipiTestContainer, Throwable, Unit] =
ZIO.serviceWithZIO[SipiTestContainer](_.copyTestFileToContainer(file, target))

/**
* A functional effect that initiates a Sipi Testcontainer
Expand Down Expand Up @@ -79,7 +90,7 @@ object SipiTestContainer {
val incunabulaImageDirPath =
Paths.get("..", "sipi/images/0803/in/cu/incunabula_0000000002.jp2")
sipiContainer.withFileSystemBind(
incunabulaImageDirPath.toString(),
incunabulaImageDirPath.toString,
"/sipi/images/0803/in/cu/incunabula_0000000002.jp2",
BindMode.READ_ONLY
)
Expand Down

0 comments on commit 85a30a5

Please sign in to comment.