Skip to content

Commit

Permalink
Also allows post for the multi-fetch operation (#4290)
Browse files Browse the repository at this point in the history
* Allow post for the multi-fetch operation

---------

Co-authored-by: Simon Dumas <[email protected]>
  • Loading branch information
imsdu and Simon Dumas authored Sep 22, 2023
1 parent 16483bc commit ae05a69
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class MultiFetchRoutes(
pathPrefix("multi-fetch") {
pathPrefix("resources") {
extractCaller { implicit caller =>
(get & entity(as[MultiFetchRequest])) { request =>
((get | post) & entity(as[MultiFetchRequest])) { request =>
implicit val printer: Printer = selectPrinter(request)
emit(multiFetch(request).flatMap(_.asJson))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ final class ResourcesTrialRoutes(
}

private def generateRoute: Route =
(get & pathPrefix("trial") & pathPrefix("resources")) {
(pathPrefix("trial") & pathPrefix("resources") & post) {
extractCaller { implicit caller =>
(resolveProjectRef & pathEndOrSingleSlash) { project =>
authorizeFor(project, Write).apply {
Expand All @@ -100,7 +100,6 @@ final class ResourcesTrialRoutes(
}
)
}

}

object ResourcesTrialRoutes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.utils.BaseRouteSpec
import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Authenticated, Group}
import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef
import ch.epfl.bluebrain.nexus.delta.sourcing.model.ResourceRef.Latest
import io.circe.Json
import monix.bio.UIO

class MultiFetchRoutesSpec extends BaseRouteSpec {
Expand Down Expand Up @@ -73,33 +74,40 @@ class MultiFetchRoutesSpec extends BaseRouteSpec {
]
}"""

def multiFetchQuery[T](payload: Json)(checks: => T) =
List(Get, Post).foreach { method =>
method(endpoint, payload.toEntity) ~> asAlice ~> routes ~> check { checks }
}

"return unauthorised results for a user with no access" in {
val entity = request(ResourceRepresentation.CompactedJsonLd).toEntity
Get(endpoint, entity) ~> routes ~> check {
status shouldEqual StatusCodes.OK
response.asJson shouldEqual jsonContentOf("multi-fetch/all-unauthorized.json")
List(Get, Post).foreach { method =>
method(endpoint, entity) ~> routes ~> check {
status shouldEqual StatusCodes.OK
response.asJson shouldEqual jsonContentOf("multi-fetch/all-unauthorized.json")
}
}
}

"return expected results as compacted json-ld for a user with limited access" in {
val entity = request(ResourceRepresentation.CompactedJsonLd).toEntity
Get(endpoint, entity) ~> asAlice ~> routes ~> check {
val payload = request(ResourceRepresentation.CompactedJsonLd)
multiFetchQuery(payload) {
status shouldEqual StatusCodes.OK
response.asJson shouldEqual jsonContentOf("multi-fetch/compacted-response.json")
}
}

"return expected results as annotated source for a user with limited access" in {
val entity = request(ResourceRepresentation.AnnotatedSourceJson).toEntity
Get(endpoint, entity) ~> asAlice ~> routes ~> check {
val payload = request(ResourceRepresentation.AnnotatedSourceJson)
multiFetchQuery(payload) {
status shouldEqual StatusCodes.OK
response.asJson shouldEqual jsonContentOf("multi-fetch/annotated-source-response.json")
}
}

"return expected results as original payloads for a user with limited access" in {
val entity = request(ResourceRepresentation.SourceJson).toEntity
Get(endpoint, entity) ~> asAlice ~> routes ~> check {
val payload = request(ResourceRepresentation.SourceJson)
multiFetchQuery(payload) {
status shouldEqual StatusCodes.OK
response.asJson shouldEqual jsonContentOf("multi-fetch/source-response.json")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ class ResourcesTrialRoutesSpec extends BaseRouteSpec with ResourceInstanceFixtur

"fail to generate a resource for a user without access" in {
val payload = json"""{ "resource": $validSource }"""
Get(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> routes ~> check {
Post(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> routes ~> check {
response.status shouldEqual StatusCodes.Forbidden
response.asJson shouldEqual jsonContentOf("errors/authorization-failed.json")
}
}

"generate a resource without passing a schema" in {
val payload = json"""{ "resource": $validSource }"""
Get(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
Post(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
response.status shouldEqual StatusCodes.OK
val jsonResponse = response.asJsonObject
jsonResponse("schema") shouldBe empty
Expand All @@ -146,9 +146,9 @@ class ResourcesTrialRoutesSpec extends BaseRouteSpec with ResourceInstanceFixtur
}
}

"generate a resource passing a new schema" in {
"generate a resource passing a new schema and using post" in {
val payload = json"""{ "schema": $schemaSource, "resource": $validSource }"""
Get(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
Post(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
response.status shouldEqual StatusCodes.OK
val jsonResponse = response.asJsonObject
jsonResponse("schema") should not be empty
Expand All @@ -159,7 +159,7 @@ class ResourcesTrialRoutesSpec extends BaseRouteSpec with ResourceInstanceFixtur

"fails to generate a resource when passing an invalid new schema" in {
val payload = json"""{ "schema": { "invalid": "xxx" }, "resource": $validSource }"""
Get(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
Post(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
response.status shouldEqual StatusCodes.BadRequest
response.asJson shouldEqual
json"""{
Expand All @@ -174,7 +174,7 @@ class ResourcesTrialRoutesSpec extends BaseRouteSpec with ResourceInstanceFixtur

"fails to generate a resource when the resource payload is invalid and without passing a schema" in {
val payload = json"""{ "resource": $invalidSource }"""
Get(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
Post(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
response.status shouldEqual StatusCodes.OK
response.asJson shouldEqual
json"""
Expand All @@ -190,7 +190,7 @@ class ResourcesTrialRoutesSpec extends BaseRouteSpec with ResourceInstanceFixtur

"fail to generate a resource passing a new schema" in {
val payload = json"""{ "schema": $schemaSource, "resource": $invalidSource }"""
Get(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
Post(s"/v1/trial/resources/$projectRef/", payload.toEntity) ~> asAlice ~> routes ~> check {
response.status shouldEqual StatusCodes.OK
val jsonResponse = response.asJsonObject
jsonResponse("schema") should not be empty
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/paradox/docs/delta/api/multi-fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Please visit @ref:[Authentication & authorization](authentication.md) section to
## Payload

```
GET /v1/multi-fetch/resources
GET|POST /v1/multi-fetch/resources
{
"format": {format}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/paradox/docs/delta/api/trial.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ It applies the same validation steps than the creation/update of resources, the
that nothing is persisted.

```
GET /v1/trial/resources/{org_label}/{project_label}
POST /v1/trial/resources/{org_label}/{project_label}
{
"schema": {schema},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package ch.epfl.bluebrain.nexus.tests.kg

import akka.http.scaladsl.model.{ContentTypes, StatusCodes}
import ch.epfl.bluebrain.nexus.tests.BaseSpec
import akka.http.scaladsl.model.{ContentTypes, HttpResponse, StatusCodes}
import ch.epfl.bluebrain.nexus.tests.{BaseSpec, Identity}
import ch.epfl.bluebrain.nexus.tests.Identity.listings.{Alice, Bob}
import ch.epfl.bluebrain.nexus.tests.Optics._
import ch.epfl.bluebrain.nexus.tests.iam.types.Permission.Resources
import ch.epfl.bluebrain.nexus.tests.resources.SimpleResource
import io.circe.Json
import org.scalatest.Assertion

class MultiFetchSpec extends BaseSpec {

Expand Down Expand Up @@ -57,14 +58,19 @@ class MultiFetchSpec extends BaseSpec {
]
}"""

def multiFetchRequest(payload: Json, identity: Identity)(check: (Json, HttpResponse) => Assertion) = {
deltaClient.getWithBody[Json]("/multi-fetch/resources", payload, identity) { check }
deltaClient.post[Json]("/multi-fetch/resources", payload, identity) { check }
}

"get all resources for a user with all access" in {
val expected = jsonContentOf(
"/kg/multi-fetch/all-success.json",
"project1" -> ref11,
"project2" -> ref12
)

deltaClient.getWithBody[Json]("/multi-fetch/resources", request("source"), Bob) { (json, response) =>
multiFetchRequest(request("source"), Bob) { (json, response) =>
response.status shouldEqual StatusCodes.OK
filterNestedKeys("_uuid")(json) shouldEqual expected
}
Expand All @@ -77,7 +83,7 @@ class MultiFetchSpec extends BaseSpec {
"project2" -> ref12
)

deltaClient.getWithBody[Json]("/multi-fetch/resources", request("source"), Alice) { (json, response) =>
multiFetchRequest(request("source"), Alice) { (json, response) =>
response.status shouldEqual StatusCodes.OK
filterNestedKeys("_uuid")(json) shouldEqual expected
}
Expand All @@ -95,12 +101,11 @@ class MultiFetchSpec extends BaseSpec {

val expected = jsonContentOf("/kg/multi-fetch/unknown.json", "project1" -> ref11)

deltaClient.getWithBody[Json]("/multi-fetch/resources", request, Bob) { (json, response) =>
multiFetchRequest(request, Bob) { (json, response) =>
response.status shouldEqual StatusCodes.OK
json shouldEqual expected
}
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ class ResourcesTrialSpec extends BaseSpec with CirceEq {
def schema = root.schema.`@id`.string.getOption(_)

"fail for a user without access" in {
deltaClient.getWithBody[Json](s"/trial/resources/$ref/", payloadWithoutSchema, Alice)(expectForbidden)
deltaClient.post[Json](s"/trial/resources/$ref/", payloadWithoutSchema, Alice)(expectForbidden)
}

"fail for an unknown project" in {
deltaClient.getWithBody[Json](s"/trial/resources/$org/xxx/", payloadWithoutSchema, Alice)(expectForbidden)
deltaClient.post[Json](s"/trial/resources/$org/xxx/", payloadWithoutSchema, Alice)(expectForbidden)
}

"succeed for a payload without schema" in {
deltaClient.getWithBody[Json](s"/trial/resources/$ref/", payloadWithoutSchema, Bob) { (json, response) =>
deltaClient.post[Json](s"/trial/resources/$ref/", payloadWithoutSchema, Bob) { (json, response) =>
response.status shouldEqual StatusCodes.OK
resultId(json).value shouldEqual resourceId
schema(json) shouldBe empty
Expand All @@ -60,7 +60,7 @@ class ResourcesTrialSpec extends BaseSpec with CirceEq {
}

"succeed for a payload with an existing schema" in {
deltaClient.getWithBody[Json](s"/trial/resources/$ref/", payloadWithExistingSchema, Bob) { (json, response) =>
deltaClient.post[Json](s"/trial/resources/$ref/", payloadWithExistingSchema, Bob) { (json, response) =>
response.status shouldEqual StatusCodes.OK
resultId(json).value shouldEqual resourceId
schema(json) shouldBe empty
Expand All @@ -69,7 +69,7 @@ class ResourcesTrialSpec extends BaseSpec with CirceEq {
}

"succeed for a payload with a new schema" in {
deltaClient.getWithBody[Json](s"/trial/resources/$ref/", payloadWithNewSchema, Bob) { (json, response) =>
deltaClient.post[Json](s"/trial/resources/$ref/", payloadWithNewSchema, Bob) { (json, response) =>
response.status shouldEqual StatusCodes.OK
resultId(json).value shouldEqual resourceId
schema(json).value shouldBe newSchemaId
Expand All @@ -79,7 +79,7 @@ class ResourcesTrialSpec extends BaseSpec with CirceEq {

"fail for a resource with an invalid context without generating any schema" in {
val payload = json"""{ "resource": { "@context": [ "https://bbp.epfl.ch/unknown-context" ], "test": "fail" } }"""
deltaClient.getWithBody[Json](s"/trial/resources/$ref/", payload, Bob) { (json, response) =>
deltaClient.post[Json](s"/trial/resources/$ref/", payload, Bob) { (json, response) =>
response.status shouldEqual StatusCodes.OK
resultId(json) shouldBe empty
schema(json) shouldBe empty
Expand All @@ -90,7 +90,7 @@ class ResourcesTrialSpec extends BaseSpec with CirceEq {
"fail for a resource with an invalid context but also returning the generated schema" in {
val resourcePayload = json"""{ "@context": [ "https://bbp.epfl.ch/unknown-context" ], "test": "fail" }"""
val payload = json"""{ "schema": $newSchemaPayload, "resource": $resourcePayload }"""
deltaClient.getWithBody[Json](s"/trial/resources/$ref/", payload, Bob) { (json, response) =>
deltaClient.post[Json](s"/trial/resources/$ref/", payload, Bob) { (json, response) =>
response.status shouldEqual StatusCodes.OK
resultId(json) shouldBe empty
schema(json).value shouldBe newSchemaId
Expand All @@ -101,7 +101,7 @@ class ResourcesTrialSpec extends BaseSpec with CirceEq {
"fail for a resource when shacl validation fails returning the generated " in {
val resourcePayload = SimpleResource.sourcePayloadWithType("nxv:UnexpectedType", 99)
val payload = json"""{ "schema": $newSchemaPayload ,"resource": $resourcePayload }"""
deltaClient.getWithBody[Json](s"/trial/resources/$ref/", payload, Bob) { (json, response) =>
deltaClient.post[Json](s"/trial/resources/$ref/", payload, Bob) { (json, response) =>
response.status shouldEqual StatusCodes.OK
resultId(json) shouldBe empty
schema(json).value shouldBe newSchemaId
Expand Down

0 comments on commit ae05a69

Please sign in to comment.