diff --git a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/ProjectsModule.scala b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/ProjectsModule.scala index df62880e45..e8c881138d 100644 --- a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/ProjectsModule.scala +++ b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/ProjectsModule.scala @@ -84,10 +84,6 @@ object ProjectsModule extends ModuleDef { Task.pure(FetchContext(organizations, projects, quotas)) } - make[ProjectContextCache].fromEffect { (fetchContext: FetchContext[ContextRejection]) => - ProjectContextCache(fetchContext) - } - make[ProjectDeletionCoordinator].fromEffect { ( projects: Projects, diff --git a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/StreamModule.scala b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/StreamModule.scala index a770e0066d..22a1b2e6a9 100644 --- a/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/StreamModule.scala +++ b/delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/StreamModule.scala @@ -2,7 +2,6 @@ package ch.epfl.bluebrain.nexus.delta.wiring import cats.effect.{Clock, Sync} import ch.epfl.bluebrain.nexus.delta.sdk.ResourceShifts -import ch.epfl.bluebrain.nexus.delta.sdk.projects.ProjectContextCache import ch.epfl.bluebrain.nexus.delta.sdk.stream.GraphResourceStream import ch.epfl.bluebrain.nexus.delta.sourcing.config.{ProjectionConfig, QueryConfig} import ch.epfl.bluebrain.nexus.delta.sourcing.projections.{ProjectionErrors, Projections} @@ -20,12 +19,11 @@ object StreamModule extends ModuleDef { make[GraphResourceStream].from { ( - contextCache: ProjectContextCache, qc: QueryConfig, xas: Transactors, shifts: ResourceShifts ) => - GraphResourceStream(contextCache.fetchContext, qc, xas, shifts) + GraphResourceStream(qc, xas, shifts) } many[PipeDef].add(DiscardMetadata) diff --git a/delta/app/src/test/resources/multi-fetch/compacted-response.json b/delta/app/src/test/resources/multi-fetch/compacted-response.json index e7dc0a0333..89db389af2 100644 --- a/delta/app/src/test/resources/multi-fetch/compacted-response.json +++ b/delta/app/src/test/resources/multi-fetch/compacted-response.json @@ -20,12 +20,12 @@ "_createdAt": "1970-01-01T00:00:00Z", "_createdBy": "http://localhost/v1/anonymous", "_deprecated": false, - "_incoming": "http://localhost/v1/resources/org/proj1/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fschemas%2Funconstrained.json/success/incoming", - "_outgoing": "http://localhost/v1/resources/org/proj1/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fschemas%2Funconstrained.json/success/outgoing", + "_incoming": "http://localhost/v1/resources/org/proj1/_/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fvocabulary%2Fsuccess/incoming", + "_outgoing": "http://localhost/v1/resources/org/proj1/_/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fvocabulary%2Fsuccess/outgoing", "_project": "http://localhost/v1/projects/org/proj1", "_rev": 1, "_schemaProject": "http://localhost/v1/projects/org/proj1", - "_self": "http://localhost/v1/resources/org/proj1/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fschemas%2Funconstrained.json/success", + "_self": "http://localhost/v1/resources/org/proj1/_/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fvocabulary%2Fsuccess", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/anonymous" } diff --git a/delta/app/src/test/resources/resolvers/resolver-route-metadata-response.json b/delta/app/src/test/resources/resolvers/resolver-route-metadata-response.json index 9e5c7fcec3..d40edf0191 100644 --- a/delta/app/src/test/resources/resolvers/resolver-route-metadata-response.json +++ b/delta/app/src/test/resources/resolvers/resolver-route-metadata-response.json @@ -9,11 +9,11 @@ "_createdAt" : "1970-01-01T00:00:00Z", "_createdBy" : "{{createdBy}}", "_deprecated" : {{deprecated}}, - "_incoming" : "http://localhost/v1/resolvers/{{project}}/{{label}}/incoming", - "_outgoing" : "http://localhost/v1/resolvers/{{project}}/{{label}}/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/{{project}}", "_rev" : {{rev}}, - "_self" : "http://localhost/v1/resolvers/{{project}}/{{label}}", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "{{updatedBy}}" } \ No newline at end of file diff --git a/delta/app/src/test/resources/resolvers/resource-resolved.json b/delta/app/src/test/resources/resolvers/resource-resolved.json index 36af74e9b8..64ba1934b5 100644 --- a/delta/app/src/test/resources/resolvers/resource-resolved.json +++ b/delta/app/src/test/resources/resolvers/resource-resolved.json @@ -11,12 +11,12 @@ "_createdAt": "1970-01-01T00:00:00Z", "_createdBy": "http://localhost/v1/anonymous", "_deprecated": false, - "_incoming": "http://localhost/v1/resources/org/project/_/resource/incoming", - "_outgoing": "http://localhost/v1/resources/org/project/_/resource/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/org/project", "_schemaProject": "http://localhost/v1/projects/org/project", "_rev": 1, - "_self": "http://localhost/v1/resources/org/project/_/resource", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/anonymous", "bool": false, diff --git a/delta/app/src/test/resources/resolvers/schema-resolved.json b/delta/app/src/test/resources/resolvers/schema-resolved.json index e9b793b629..8176970e8c 100644 --- a/delta/app/src/test/resources/resolvers/schema-resolved.json +++ b/delta/app/src/test/resources/resolvers/schema-resolved.json @@ -13,11 +13,11 @@ "_createdAt": "1970-01-01T00:00:00Z", "_createdBy": "http://localhost/v1/anonymous", "_deprecated": false, - "_incoming": "http://localhost/v1/schemas/org/project/schemaId/incoming", - "_outgoing": "http://localhost/v1/schemas/org/project/schemaId/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/org/project", "_rev": 1, - "_self": "http://localhost/v1/schemas/org/project/schemaId", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/anonymous", "shapes": [ diff --git a/delta/app/src/test/resources/resources/resource-route-metadata-response.json b/delta/app/src/test/resources/resources/resource-route-metadata-response.json index a81bc2d685..b61719461a 100644 --- a/delta/app/src/test/resources/resources/resource-route-metadata-response.json +++ b/delta/app/src/test/resources/resources/resource-route-metadata-response.json @@ -6,12 +6,12 @@ "_createdAt" : "1970-01-01T00:00:00Z", "_createdBy" : "{{createdBy}}", "_deprecated" : {{deprecated}}, - "_incoming" : "http://localhost/v1/resources/{{project}}/{{schemaLabel}}/{{label}}/incoming", - "_outgoing" : "http://localhost/v1/resources/{{project}}/{{schemaLabel}}/{{label}}/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/{{project}}", "_rev" : {{rev}}, "_schemaProject" : "http://localhost/v1/projects/{{project}}", - "_self" : "http://localhost/v1/resources/{{project}}/{{schemaLabel}}/{{label}}", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "{{updatedBy}}" } \ No newline at end of file diff --git a/delta/app/src/test/resources/schemas/schema-created-response.json b/delta/app/src/test/resources/schemas/schema-created-response.json index cc883ad02b..5a8e2819a1 100644 --- a/delta/app/src/test/resources/schemas/schema-created-response.json +++ b/delta/app/src/test/resources/schemas/schema-created-response.json @@ -13,11 +13,11 @@ "_createdAt" : "1970-01-01T00:00:00Z", "_createdBy" : "http://localhost/v1/realms/wonderland/users/alice", "_deprecated" : false, - "_incoming" : "http://localhost/v1/schemas/myorg/myproject/myid2/incoming", - "_outgoing" : "http://localhost/v1/schemas/myorg/myproject/myid2/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/myorg/myproject", "_rev" : 1, - "_self" : "http://localhost/v1/schemas/myorg/myproject/myid2", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "http://localhost/v1/realms/wonderland/users/alice", "shapes" : [ diff --git a/delta/app/src/test/resources/schemas/schema-route-metadata-response.json b/delta/app/src/test/resources/schemas/schema-route-metadata-response.json index 25601d24ee..be6b163a17 100644 --- a/delta/app/src/test/resources/schemas/schema-route-metadata-response.json +++ b/delta/app/src/test/resources/schemas/schema-route-metadata-response.json @@ -9,11 +9,11 @@ "_createdAt" : "1970-01-01T00:00:00Z", "_createdBy" : "{{createdBy}}", "_deprecated" : {{deprecated}}, - "_incoming" : "http://localhost/v1/schemas/{{project}}/{{label}}/incoming", - "_outgoing" : "http://localhost/v1/schemas/{{project}}/{{label}}/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/{{project}}", "_rev" : {{rev}}, - "_self" : "http://localhost/v1/schemas/{{project}}/{{label}}", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "{{updatedBy}}" } \ No newline at end of file diff --git a/delta/app/src/test/resources/schemas/schema-updated-response.json b/delta/app/src/test/resources/schemas/schema-updated-response.json index 7637df7504..843e66fb35 100644 --- a/delta/app/src/test/resources/schemas/schema-updated-response.json +++ b/delta/app/src/test/resources/schemas/schema-updated-response.json @@ -13,11 +13,11 @@ "_createdAt": "1970-01-01T00:00:00Z", "_createdBy": "http://localhost/v1/anonymous", "_deprecated": true, - "_incoming": "http://localhost/v1/schemas/myorg/myproject/myid/incoming", - "_outgoing": "http://localhost/v1/schemas/myorg/myproject/myid/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/myorg/myproject", "_rev": 6, - "_self": "http://localhost/v1/schemas/myorg/myproject/myid", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/anonymous", "shapes": [ diff --git a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResolversRoutesSpec.scala b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResolversRoutesSpec.scala index 750e6ce899..aa0d40da91 100644 --- a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResolversRoutesSpec.scala +++ b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResolversRoutesSpec.scala @@ -7,7 +7,6 @@ import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.delta.kernel.utils.{UUIDF, UrlUtils} import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.{contexts, nxv, schema, schemas} -import ch.epfl.bluebrain.nexus.delta.sdk.{Defaults, IndexingAction} import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclSimpleCheck import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress import ch.epfl.bluebrain.nexus.delta.sdk.directives.DeltaSchemeDirectives @@ -16,6 +15,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.identities.IdentitiesDummy import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.Caller import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdContent +import ch.epfl.bluebrain.nexus.delta.sdk.model.ResourceUris import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContextDummy import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings @@ -23,10 +23,10 @@ import ch.epfl.bluebrain.nexus.delta.sdk.resolvers._ import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverRejection.ProjectContextRejection import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverType.{CrossProject, InProject} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.{ResolverRejection, ResolverType, ResourceResolutionReport} -import ch.epfl.bluebrain.nexus.delta.sdk.resources.Resources import ch.epfl.bluebrain.nexus.delta.sdk.resources.model.Resource import ch.epfl.bluebrain.nexus.delta.sdk.schemas.model.Schema import ch.epfl.bluebrain.nexus.delta.sdk.utils.BaseRouteSpec +import ch.epfl.bluebrain.nexus.delta.sdk.{Defaults, IndexingAction} import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Authenticated, Group, Subject} import ch.epfl.bluebrain.nexus.delta.sourcing.model.ResourceRef.{Latest, Revision} import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Label, ProjectRef, ResourceRef} @@ -45,13 +45,12 @@ class ResolversRoutesSpec extends BaseRouteSpec { private val asAlice = addCredentials(OAuth2BearerToken(alice.subject)) private val asBob = addCredentials(OAuth2BearerToken(bob.subject)) - private val org = Label.unsafe("org") - private val defaultApiMappings = Resources.mappings - private val am = ApiMappings("nxv" -> nxv.base, "Person" -> schema.Person, "resolver" -> schemas.resolvers) - private val projBase = nxv.base - private val project = + private val org = Label.unsafe("org") + private val am = ApiMappings("nxv" -> nxv.base, "Person" -> schema.Person, "resolver" -> schemas.resolvers) + private val projBase = nxv.base + private val project = ProjectGen.project("org", "project", uuid = uuid, orgUuid = uuid, base = projBase, mappings = am) - private val project2 = + private val project2 = ProjectGen.project("org", "project2", uuid = uuid, orgUuid = uuid, base = projBase, mappings = am) private val identities = IdentitiesDummy( @@ -67,7 +66,7 @@ class ResolversRoutesSpec extends BaseRouteSpec { private val resourceId = nxv + "resource" private val resource = ResourceGen.resource(resourceId, project.ref, jsonContentOf("resources/resource.json", "id" -> resourceId)) - private val resourceFR = ResourceGen.resourceFor(resource, types = Set(nxv + "Custom"), am = defaultApiMappings) + private val resourceFR = ResourceGen.resourceFor(resource, types = Set(nxv + "Custom")) private val schemaId = nxv + "schemaId" private val schemaResource = SchemaGen.schema( @@ -724,13 +723,23 @@ class ResolversRoutesSpec extends BaseRouteSpec { val idSchemaEncoded = UrlUtils.encode(schemaId.toString) val unknownResourceEncoded = UrlUtils.encode((nxv + "xxx").toString) + val resourceResolved = jsonContentOf( + "resolvers/resource-resolved.json", + "self" -> ResourceUris.resource(project.ref, project.ref, resourceId).accessUri + ) + + val schemaResolved = jsonContentOf( + "resolvers/schema-resolved.json", + "self" -> ResourceUris.schema(project.ref, schemaId).accessUri + ) + "resolve the resources/schemas" should { "succeed as a resource for the given id" in { // First we resolve with a in-project resolver, the second one with a cross-project resolver forAll(List(project, project2)) { p => Get(s"/v1/resolvers/${p.ref}/_/$idResourceEncoded") ~> asAlice ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf("resolvers/resource-resolved.json") + response.asJson shouldEqual resourceResolved } } } @@ -747,7 +756,7 @@ class ResolversRoutesSpec extends BaseRouteSpec { case (p, resolver) => Get(s"/v1/resolvers/${p.ref}/$resolver/$idResourceEncoded") ~> asAlice ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf("resolvers/resource-resolved.json") + response.asJson shouldEqual resourceResolved } } } @@ -766,7 +775,7 @@ class ResolversRoutesSpec extends BaseRouteSpec { forAll(List(project, project2)) { p => Get(s"/v1/resolvers/${p.ref}/_/$idSchemaEncoded?rev=5") ~> asAlice ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf("resolvers/schema-resolved.json") + response.asJson shouldEqual schemaResolved } } } @@ -783,7 +792,7 @@ class ResolversRoutesSpec extends BaseRouteSpec { case (p, resolver) => Get(s"/v1/resolvers/${p.ref}/$resolver/$idSchemaEncoded?rev=5") ~> asAlice ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf("resolvers/schema-resolved.json") + response.asJson shouldEqual schemaResolved } } } @@ -849,6 +858,6 @@ class ResolversRoutesSpec extends BaseRouteSpec { "createdBy" -> createdBy.asIri, "updatedBy" -> updatedBy.asIri, "type" -> resolverType, - "label" -> lastSegment(id) + "self" -> ResourceUris.resolver(projectRef, id).accessUri ) } diff --git a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResourcesRoutesSpec.scala b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResourcesRoutesSpec.scala index 337ae755b8..2e38cf6810 100644 --- a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResourcesRoutesSpec.scala +++ b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/ResourcesRoutesSpec.scala @@ -16,6 +16,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.generators.{ProjectGen, ResourceResolut import ch.epfl.bluebrain.nexus.delta.sdk.identities.IdentitiesDummy import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.Caller import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ +import ch.epfl.bluebrain.nexus.delta.sdk.model.ResourceUris import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.{events, resources} import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContextDummy import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings @@ -71,7 +72,11 @@ class ResourcesRoutesSpec extends BaseRouteSpec { private val payloadWithBlankId = jsonContentOf("resources/resource.json", "id" -> "") private val payloadWithUnderscoreFields = jsonContentOf("resources/resource-with-underscore-fields.json", "id" -> myId5) - private val payloadWithMetadata = jsonContentOf("resources/resource-with-metadata.json", "id" -> myId) + private val payloadWithMetadata = jsonContentOf( + "resources/resource-with-metadata.json", + "id" -> myId, + "self" -> ResourceUris.resource(projectRef, projectRef, myId).accessUri + ) private val aclCheck = AclSimpleCheck().accepted @@ -568,7 +573,7 @@ class ResourcesRoutesSpec extends BaseRouteSpec { } def resourceMetadata( - ref: ProjectRef, + project: ProjectRef, id: Iri, schema: Iri, tpe: String, @@ -579,16 +584,15 @@ class ResourcesRoutesSpec extends BaseRouteSpec { ): Json = jsonContentOf( "resources/resource-route-metadata-response.json", - "project" -> ref, - "id" -> id, - "rev" -> rev, - "type" -> tpe, - "deprecated" -> deprecated, - "createdBy" -> createdBy.asIri, - "updatedBy" -> updatedBy.asIri, - "schema" -> schema, - "label" -> lastSegment(id), - "schemaLabel" -> (if (schema == schemas.resources) "_" else lastSegment(schema)) + "project" -> project, + "id" -> id, + "rev" -> rev, + "type" -> tpe, + "deprecated" -> deprecated, + "createdBy" -> createdBy.asIri, + "updatedBy" -> updatedBy.asIri, + "schema" -> schema, + "self" -> ResourceUris.resource(project, project, id).accessUri ) } diff --git a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/SchemasRoutesSpec.scala b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/SchemasRoutesSpec.scala index 95f708632c..9023feae20 100644 --- a/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/SchemasRoutesSpec.scala +++ b/delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/SchemasRoutesSpec.scala @@ -17,6 +17,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.generators.ProjectGen import ch.epfl.bluebrain.nexus.delta.sdk.identities.IdentitiesDummy import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.Caller import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ +import ch.epfl.bluebrain.nexus.delta.sdk.model.ResourceUris import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.{events, resources, schemas} import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContextDummy import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings @@ -264,7 +265,11 @@ class SchemasRoutesSpec extends BaseRouteSpec { forAll(endpoints) { endpoint => Get(endpoint) ~> routes ~> check { status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf("schemas/schema-updated-response.json", "id" -> "nxv:myid") + response.asJson shouldEqual jsonContentOf( + "schemas/schema-updated-response.json", + "id" -> "nxv:myid", + "self" -> ResourceUris.schema(projectRef, myId).accessUri + ) } } } @@ -285,7 +290,11 @@ class SchemasRoutesSpec extends BaseRouteSpec { forAll(List("rev=1", "tag=mytag")) { param => Get(s"$endpoint?$param") ~> routes ~> check { status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf("schemas/schema-created-response.json", "id" -> "nxv:myid2") + response.asJson shouldEqual jsonContentOf( + "schemas/schema-created-response.json", + "id" -> "nxv:myid2", + "self" -> ResourceUris.schema(projectRef, myId2).accessUri + ) } } } @@ -388,7 +397,7 @@ class SchemasRoutesSpec extends BaseRouteSpec { } private def schemaMetadata( - ref: ProjectRef, + project: ProjectRef, id: Iri, rev: Int = 1, deprecated: Boolean = false, @@ -397,12 +406,12 @@ class SchemasRoutesSpec extends BaseRouteSpec { ): Json = jsonContentOf( "schemas/schema-route-metadata-response.json", - "project" -> ref, + "project" -> project, "id" -> id, "rev" -> rev, "deprecated" -> deprecated, "createdBy" -> createdBy.asIri, "updatedBy" -> updatedBy.asIri, - "label" -> lastSegment(id) + "self" -> ResourceUris.schema(project, id).accessUri ) } diff --git a/delta/plugins/archive/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/Archives.scala b/delta/plugins/archive/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/Archives.scala index 1ba4e2722a..e451e6fdde 100644 --- a/delta/plugins/archive/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/Archives.scala +++ b/delta/plugins/archive/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/Archives.scala @@ -17,7 +17,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.ExpandIri import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdSourceProcessor.JsonLdSourceDecoder import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegment import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectContext} +import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings import ch.epfl.bluebrain.nexus.delta.sourcing.config.EphemeralLogConfig import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.{EntityType, ProjectRef} @@ -90,7 +90,7 @@ class Archives( (for { p <- fetchContext.onRead(project) iri <- expandIri(id, p) - res <- eval(CreateArchive(iri, project, value, subject), p) + res <- eval(CreateArchive(iri, project, value, subject)) } yield res).span("createArchive") /** @@ -108,7 +108,7 @@ class Archives( (for { p <- fetchContext.onRead(project) (iri, value) <- sourceDecoder(p, source) - res <- eval(CreateArchive(iri, project, value, subject), p) + res <- eval(CreateArchive(iri, project, value, subject)) } yield res).span("createArchive") /** @@ -134,7 +134,7 @@ class Archives( p <- fetchContext.onRead(project) iri <- expandIri(id, p) value <- sourceDecoder(p, iri, source) - res <- eval(CreateArchive(iri, project, value, subject), p) + res <- eval(CreateArchive(iri, project, value, subject)) } yield res).span("createArchive") /** @@ -150,7 +150,7 @@ class Archives( p <- fetchContext.onRead(project) iri <- expandIri(id, p) state <- log.stateOr(project, iri, ArchiveNotFound(iri, project)) - res = state.toResource(p.apiMappings, p.base, config.ttl) + res = state.toResource(config.ttl) } yield res).span("fetchArchive") /** @@ -175,10 +175,8 @@ class Archives( source <- archiveDownload(value.value, project, format, ignoreNotFound) } yield source).span("downloadArchive") - private def eval(cmd: CreateArchive, pc: ProjectContext): IO[ArchiveRejection, ArchiveResource] = - log.evaluate(cmd.project, cmd.id, cmd).map { - _.toResource(pc.apiMappings, pc.base, config.ttl) - } + private def eval(cmd: CreateArchive): IO[ArchiveRejection, ArchiveResource] = + log.evaluate(cmd.project, cmd.id, cmd).map { _.toResource(config.ttl) } } object Archives { diff --git a/delta/plugins/archive/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/model/ArchiveState.scala b/delta/plugins/archive/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/model/ArchiveState.scala index 49d6b26768..e27a0d5851 100644 --- a/delta/plugins/archive/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/model/ArchiveState.scala +++ b/delta/plugins/archive/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/model/ArchiveState.scala @@ -5,7 +5,6 @@ import ch.epfl.bluebrain.nexus.delta.plugins.archive.model import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.instances._ import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceRepresentation, ResourceUris} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} @@ -44,10 +43,10 @@ final case class ArchiveState( override def types: Set[Iri] = Set(tpe) - def toResource(mappings: ApiMappings, base: ProjectBase, ttl: FiniteDuration): ArchiveResource = + def toResource(ttl: FiniteDuration): ArchiveResource = ResourceF( id = id, - uris = ResourceUris.ephemeral("archives", project, id)(mappings, base), + uris = ResourceUris.ephemeral("archives", project, id), rev = this.rev, types = this.types, deprecated = this.deprecated, diff --git a/delta/plugins/archive/src/test/resources/responses/archive-metadata-response.json b/delta/plugins/archive/src/test/resources/responses/archive-metadata-response.json index 85de84305f..3d224ddfbf 100644 --- a/delta/plugins/archive/src/test/resources/responses/archive-metadata-response.json +++ b/delta/plugins/archive/src/test/resources/responses/archive-metadata-response.json @@ -12,7 +12,7 @@ "_expiresInSeconds": {{expiresInSeconds}}, "_project" : "http://localhost/v1/projects/{{project}}", "_rev" : {{rev}}, - "_self" : "http://localhost/v1/archives/{{project}}/{{label}}", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "{{updatedBy}}" } \ No newline at end of file diff --git a/delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchiveRoutesSpec.scala b/delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchiveRoutesSpec.scala index 80c061e04a..1081083c4a 100644 --- a/delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchiveRoutesSpec.scala +++ b/delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchiveRoutesSpec.scala @@ -34,7 +34,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.identities.IdentitiesDummy import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.Caller import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdContent -import ch.epfl.bluebrain.nexus.delta.sdk.model.ResourceF +import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris} import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions import ch.epfl.bluebrain.nexus.delta.sdk.permissions.model.Permission import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContextDummy @@ -161,23 +161,22 @@ class ArchiveRoutesSpec extends BaseRouteSpec with StorageFixtures with TryValue private def archiveMetadata( id: Iri, - ref: ProjectRef, + project: ProjectRef, rev: Int = 1, deprecated: Boolean = false, createdBy: Subject = subject, updatedBy: Subject = subject, - expiresInSeconds: Long = 18000L, - label: Option[String] = None + expiresInSeconds: Long = 18000L ): Json = jsonContentOf( "responses/archive-metadata-response.json", - "project" -> ref, + "project" -> project, "id" -> id, "rev" -> rev, "deprecated" -> deprecated, "createdBy" -> createdBy.asIri, "updatedBy" -> updatedBy.asIri, - "label" -> label.fold(lastSegment(id))(identity), + "self" -> ResourceUris.ephemeral("archives", project, id).accessUri, "expiresInSeconds" -> expiresInSeconds.toString ) @@ -250,7 +249,7 @@ class ArchiveRoutesSpec extends BaseRouteSpec with StorageFixtures with TryValue val encodedId = encode(id.toString).replaceAll("%3A", ":") Put(s"/v1/archives/$projectRef/$encodedId", archive.toEntity) ~> asSubject ~> acceptMeta ~> routes ~> check { status shouldEqual StatusCodes.Created - response.asJson shouldEqual archiveMetadata(id, project.ref, label = Some(encodedId)) + response.asJson shouldEqual archiveMetadata(id, project.ref) } } @@ -263,7 +262,7 @@ class ArchiveRoutesSpec extends BaseRouteSpec with StorageFixtures with TryValue archiveWithFileSelf.toEntity ) ~> asSubject ~> acceptMeta ~> routes ~> check { status shouldEqual StatusCodes.Created - response.asJson shouldEqual archiveMetadata(id, project.ref, label = Some(encodedId)) + response.asJson shouldEqual archiveMetadata(id, project.ref) } } @@ -309,8 +308,7 @@ class ArchiveRoutesSpec extends BaseRouteSpec with StorageFixtures with TryValue file.value.attributes, storageRef, createdBy = subject, - updatedBy = subject, - label = Some(encodedFileId.replaceAll("%3A", ":")) + updatedBy = subject ) val actualMetadata = result.entryAsJson(s"${project.ref}/compacted/${encode(fileId.toString)}.json") actualMetadata shouldEqual expectedMetadata @@ -341,8 +339,7 @@ class ArchiveRoutesSpec extends BaseRouteSpec with StorageFixtures with TryValue file.value.attributes, storageRef, createdBy = subject, - updatedBy = subject, - label = Some(encodedFileId.replaceAll("%3A", ":")) + updatedBy = subject ) val actualMetadata = result.entryAsJson(s"${project.ref}/compacted/${encode(fileId.toString)}.json") actualMetadata shouldEqual expectedMetadata diff --git a/delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchivesSpec.scala b/delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchivesSpec.scala index 835cc0334b..5d1c49abc5 100644 --- a/delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchivesSpec.scala +++ b/delta/plugins/archive/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/archive/ArchivesSpec.scala @@ -111,12 +111,10 @@ class ArchivesSpec resource.rev shouldEqual 1L val id = resource.id - val uuid = id.toString.substring(id.toString.lastIndexOf('/') + 1) val encodedId = URLEncoder.encode(id.toString, StandardCharsets.UTF_8) resource.uris shouldEqual EphemeralResourceInProjectUris( project.ref, - s"archives/${project.ref}/$encodedId", - s"archives/${project.ref}/$uuid" + s"archives/${project.ref}/$encodedId" ) } @@ -196,12 +194,10 @@ class ArchivesSpec val resource = archives.create(project.ref, value).accepted val id = resource.id - val uuid = id.toString.substring(id.toString.lastIndexOf('/') + 1) val encodedId = URLEncoder.encode(id.toString, StandardCharsets.UTF_8) resource.uris shouldEqual EphemeralResourceInProjectUris( project.ref, - s"archives/${project.ref}/$encodedId", - s"archives/${project.ref}/$uuid" + s"archives/${project.ref}/$encodedId" ) resource.id shouldEqual id @@ -237,13 +233,11 @@ class ArchivesSpec archives.create(id, project.ref, value).accepted val resource = archives.fetch(id, project.ref).accepted - val uuid = id.toString.substring(id.toString.lastIndexOf('/') + 1) val encodedId = URLEncoder.encode(id.toString, StandardCharsets.UTF_8) resource.id shouldEqual id resource.uris shouldEqual EphemeralResourceInProjectUris( project.ref, - s"archives/${project.ref}/$encodedId", - s"archives/${project.ref}/$uuid" + s"archives/${project.ref}/$encodedId" ) resource.createdBy shouldEqual bob resource.updatedBy shouldEqual bob diff --git a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViews.scala b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViews.scala index ca16cc06ce..a81103a9dc 100644 --- a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViews.scala +++ b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViews.scala @@ -25,7 +25,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdSourceProcessor.JsonLdSour import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegmentRef.{Latest, Revision, Tag} import ch.epfl.bluebrain.nexus.delta.sdk.model._ import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectContext} +import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolverContextResolution import ch.epfl.bluebrain.nexus.delta.sourcing.ScopedEntityDefinition.Tagger import ch.epfl.bluebrain.nexus.delta.sourcing._ @@ -65,7 +65,7 @@ final class BlazegraphViews( for { pc <- fetchContext.onCreate(project) (iri, viewValue) <- sourceDecoder(project, pc, source) - res <- eval(CreateBlazegraphView(iri, project, viewValue, source, caller.subject), pc) + res <- eval(CreateBlazegraphView(iri, project, viewValue, source, caller.subject)) _ <- createNamespace(res) } yield res }.span("createBlazegraphView") @@ -89,7 +89,7 @@ final class BlazegraphViews( pc <- fetchContext.onCreate(project) iri <- expandIri(id, pc) viewValue <- sourceDecoder(project, pc, iri, source) - res <- eval(CreateBlazegraphView(iri, project, viewValue, source, caller.subject), pc) + res <- eval(CreateBlazegraphView(iri, project, viewValue, source, caller.subject)) _ <- createNamespace(res) } yield res }.span("createBlazegraphView") @@ -110,7 +110,7 @@ final class BlazegraphViews( pc <- fetchContext.onCreate(project) iri <- expandIri(id, pc) source = view.toJson(iri) - res <- eval(CreateBlazegraphView(iri, project, view, source, subject), pc) + res <- eval(CreateBlazegraphView(iri, project, view, source, subject)) _ <- createNamespace(res) } yield res }.span("createBlazegraphView") @@ -136,7 +136,7 @@ final class BlazegraphViews( pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) viewValue <- sourceDecoder(project, pc, iri, source) - res <- eval(UpdateBlazegraphView(iri, project, viewValue, rev, source, caller.subject), pc) + res <- eval(UpdateBlazegraphView(iri, project, viewValue, rev, source, caller.subject)) _ <- createNamespace(res) } yield res }.span("updateBlazegraphView") @@ -160,7 +160,7 @@ final class BlazegraphViews( pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) source = view.toJson(iri) - res <- eval(UpdateBlazegraphView(iri, project, view, rev, source, subject), pc) + res <- eval(UpdateBlazegraphView(iri, project, view, rev, source, subject)) _ <- createNamespace(res) } yield res }.span("updateBlazegraphView") @@ -189,7 +189,7 @@ final class BlazegraphViews( for { pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) - res <- eval(TagBlazegraphView(iri, project, tagRev, tag, rev, subject), pc) + res <- eval(TagBlazegraphView(iri, project, tagRev, tag, rev, subject)) _ <- createNamespace(res) } yield res }.span("tagBlazegraphView") @@ -212,7 +212,7 @@ final class BlazegraphViews( for { pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) - res <- eval(DeprecateBlazegraphView(iri, project, rev, subject), pc) + res <- eval(DeprecateBlazegraphView(iri, project, rev, subject)) } yield res }.span("deprecateBlazegraphView") @@ -240,14 +240,12 @@ final class BlazegraphViews( * the project to which the view belongs */ def fetch(id: IdSegmentRef, project: ProjectRef): IO[BlazegraphViewRejection, ViewResource] = - fetchState(id, project).map { case (pc, state) => - state.toResource(pc.apiMappings, pc.base) - } + fetchState(id, project).map(_.toResource) def fetchState( id: IdSegmentRef, project: ProjectRef - ): IO[BlazegraphViewRejection, (ProjectContext, BlazegraphViewState)] = { + ): IO[BlazegraphViewRejection, BlazegraphViewState] = { for { pc <- fetchContext.onRead(project) iri <- expandIri(id.value, pc) @@ -259,7 +257,7 @@ final class BlazegraphViews( case Tag(_, tag) => log.stateOr(project, iri, tag, notFound, TagNotFound(tag)) } - } yield (pc, state) + } yield state }.span("fetchBlazegraphView") /** @@ -274,7 +272,7 @@ final class BlazegraphViews( id: IdSegmentRef, project: ProjectRef ): IO[BlazegraphViewRejection, ActiveViewDef] = - fetchState(id, project).flatMap { case (_, state) => + fetchState(id, project).flatMap { state => IndexingViewDef(state, prefix) match { case Some(viewDef) => viewDef match { @@ -318,12 +316,8 @@ final class BlazegraphViews( IndexingViewDef(v, prefix) } - private def eval(cmd: BlazegraphViewCommand) = - log.evaluate(cmd.project, cmd.id, cmd) - - private def eval(cmd: BlazegraphViewCommand, pc: ProjectContext): IO[BlazegraphViewRejection, ViewResource] = - eval(cmd) - .map(_._2.toResource(pc.apiMappings, pc.base)) + private def eval(cmd: BlazegraphViewCommand): IO[BlazegraphViewRejection, ViewResource] = + log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource) } object BlazegraphViews { diff --git a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViewsQuery.scala b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViewsQuery.scala index 8c3d8343ef..4cfff1f640 100644 --- a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViewsQuery.scala +++ b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViewsQuery.scala @@ -1,5 +1,6 @@ package ch.epfl.bluebrain.nexus.delta.plugins.blazegraph +import ch.epfl.bluebrain.nexus.delta.kernel.search.Pagination.FromPagination import ch.epfl.bluebrain.nexus.delta.kernel.utils.ClasspathResourceUtils.ioContentOf import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.client.SparqlQueryResponseType.{Aux, SparqlResultsJson} import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.client._ @@ -15,13 +16,11 @@ import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress.{Project => Proje import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.Caller import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.ExpandIri import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegment.IriSegment -import ch.epfl.bluebrain.nexus.delta.kernel.search.Pagination.FromPagination import ch.epfl.bluebrain.nexus.delta.sdk.model.search.ResultEntry.UnscoredResultEntry import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchResults import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchResults.UnscoredSearchResults import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, IdSegment} import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sdk.views.View.{AggregateView, IndexingView} import ch.epfl.bluebrain.nexus.delta.sdk.views.{ViewRef, ViewsStore} import ch.epfl.bluebrain.nexus.delta.sourcing.Transactors @@ -109,7 +108,7 @@ object BlazegraphViewsQuery { BlazegraphViews.entityType, BlazegraphViewState.serializer, defaultViewId, - views.fetchState(_, _).map(_._2), + views.fetchState, view => IO.raiseWhen(view.deprecated)(ViewIsDeprecated(view.id)).as { view.value match { @@ -146,7 +145,7 @@ object BlazegraphViewsQuery { iri <- expandIri(id, p) q = SparqlQuery(replace(incomingQuery, iri, pagination)) bindings <- query(IriSegment(defaultViewId), projectRef, q, SparqlResultsJson) - links = toSparqlLinks(bindings.value, p.apiMappings, p.base) + links = toSparqlLinks(bindings.value) } yield links override def outgoing( @@ -161,7 +160,7 @@ object BlazegraphViewsQuery { queryTemplate = if (includeExternalLinks) outgoingWithExternalQuery else outgoingScopedQuery q = SparqlQuery(replace(queryTemplate, iri, pagination)) bindings <- query(IriSegment(defaultViewId), projectRef, q, SparqlResultsJson) - links = toSparqlLinks(bindings.value, p.apiMappings, p.base) + links = toSparqlLinks(bindings.value) } yield links override def query[R <: SparqlQueryResponse]( @@ -192,14 +191,14 @@ object BlazegraphViewsQuery { ) } yield qr - private def toSparqlLinks(sparqlResults: SparqlResults, mappings: ApiMappings, projectBase: ProjectBase)(implicit + private def toSparqlLinks(sparqlResults: SparqlResults)(implicit base: BaseUri ): SearchResults[SparqlLink] = { val (count, results) = sparqlResults.results.bindings .foldLeft((0L, List.empty[SparqlLink])) { case ((total, acc), bindings) => val newTotal = bindings.get("total").flatMap(v => v.value.toLongOption).getOrElse(total) - val res = (SparqlResourceLink(bindings, mappings, projectBase) orElse SparqlExternalLink(bindings)) + val res = (SparqlResourceLink(bindings) orElse SparqlExternalLink(bindings)) .map(_ :: acc) .getOrElse(acc) (newTotal, res) diff --git a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/BlazegraphView.scala b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/BlazegraphView.scala index 6ec1d818cf..0c4be12686 100644 --- a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/BlazegraphView.scala +++ b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/BlazegraphView.scala @@ -197,7 +197,7 @@ object BlazegraphView { ResourceShift.withMetadata[BlazegraphViewState, BlazegraphView, Metadata]( BlazegraphViews.entityType, (ref, project) => views.fetch(IdSegmentRef(ref), project), - (context, state) => state.toResource(context.apiMappings, context.base), + state => state.toResource, value => JsonLdContent(value, value.value.source, Some(value.value.metadata)) ) } diff --git a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/BlazegraphViewState.scala b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/BlazegraphViewState.scala index eb2949345f..1905c69da1 100644 --- a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/BlazegraphViewState.scala +++ b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/BlazegraphViewState.scala @@ -5,7 +5,6 @@ import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.model.BlazegraphView._ import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.model.BlazegraphViewValue._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} @@ -100,10 +99,10 @@ final case class BlazegraphViewState( AggregateBlazegraphView(id, name, description, project, views, tags, source) } - def toResource(mappings: ApiMappings, base: ProjectBase): ViewResource = + def toResource: ViewResource = ResourceF( id = id, - uris = ResourceUris("views", project, id)(mappings, base), + uris = ResourceUris("views", project, id), rev = rev, types = value.tpe.types, deprecated = deprecated, diff --git a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/SparqlLink.scala b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/SparqlLink.scala index c867ad1849..dd10fc4b56 100644 --- a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/SparqlLink.scala +++ b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/model/SparqlLink.scala @@ -5,10 +5,8 @@ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, ResourceF, ResourceUris} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject -import ch.epfl.bluebrain.nexus.delta.sourcing.model.ResourceRef -import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef +import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} import io.circe.syntax.EncoderOps import io.circe.{Encoder, Json, JsonObject} @@ -60,11 +58,8 @@ object SparqlLink { private def resourceUrisFor( project: ProjectRef, schemaProject: ProjectRef, - id: Iri, - schema: ResourceRef, - mappings: ApiMappings, - projectBase: ProjectBase - ): ResourceUris = ResourceUris.resource(project, schemaProject, id, schema)(mappings, projectBase) + id: Iri + ): ResourceUris = ResourceUris.resource(project, schemaProject, id) /** * Attempts to create a [[SparqlResourceLink]] from the given bindings @@ -72,11 +67,7 @@ object SparqlLink { * @param bindings * the sparql result bindings */ - def apply( - bindings: Map[String, Binding], - mappings: ApiMappings, - projectBase: ProjectBase - )(implicit base: BaseUri): Option[SparqlLink] = + def apply(bindings: Map[String, Binding])(implicit base: BaseUri): Option[SparqlLink] = for { link <- SparqlExternalLink(bindings) project <- @@ -97,7 +88,7 @@ object SparqlLink { .flatMap(Iri.absolute(_).toOption) .flatMap(projectRefFromId) .getOrElse(project) - resourceUris = resourceUrisFor(project, schemaProject, link.id, schemaRef, mappings, projectBase) + resourceUris = resourceUrisFor(project, schemaProject, link.id) } yield SparqlResourceLink( ResourceF( link.id, diff --git a/delta/plugins/blazegraph/src/test/resources/routes/responses/aggregate-view-metadata.json b/delta/plugins/blazegraph/src/test/resources/routes/responses/aggregate-view-metadata.json index dbb167ec83..3bc4946597 100644 --- a/delta/plugins/blazegraph/src/test/resources/routes/responses/aggregate-view-metadata.json +++ b/delta/plugins/blazegraph/src/test/resources/routes/responses/aggregate-view-metadata.json @@ -12,11 +12,11 @@ "_createdAt": "1970-01-01T00:00:00Z", "_createdBy": "http://localhost/v1/realms/myrealm/users/Bob", "_deprecated": false, - "_incoming": "http://localhost/v1/views/org/proj/aggregate-view/incoming", - "_outgoing": "http://localhost/v1/views/org/proj/aggregate-view/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/org/proj", "_rev": 1, - "_self": "http://localhost/v1/views/org/proj/aggregate-view", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/realms/myrealm/users/Bob" } \ No newline at end of file diff --git a/delta/plugins/blazegraph/src/test/resources/routes/responses/incoming-outgoing.json b/delta/plugins/blazegraph/src/test/resources/routes/responses/incoming-outgoing.json index 16fb1b0a93..70163045fd 100644 --- a/delta/plugins/blazegraph/src/test/resources/routes/responses/incoming-outgoing.json +++ b/delta/plugins/blazegraph/src/test/resources/routes/responses/incoming-outgoing.json @@ -21,11 +21,11 @@ "_project": "http://localhost/v1/projects/org/proj", "_schemaProject" : "http://localhost/v1/projects/org/proj", "_rev": 1, - "_self" : "http://localhost/v1/resources/org/proj/example:someSchema/example:id1", + "_self" : "http://localhost/v1/resources/org/proj/_/http:%2F%2Fexample.com%2Fid1", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/anonymous", - "_incoming" : "http://localhost/v1/resources/org/proj/example:someSchema/example:id1/incoming", - "_outgoing" : "http://localhost/v1/resources/org/proj/example:someSchema/example:id1/outgoing" + "_incoming" : "http://localhost/v1/resources/org/proj/_/http:%2F%2Fexample.com%2Fid1/incoming", + "_outgoing" : "http://localhost/v1/resources/org/proj/_/http:%2F%2Fexample.com%2Fid1/outgoing" }, { "@id": "http://example.com/external", diff --git a/delta/plugins/blazegraph/src/test/resources/routes/responses/indexing-view-metadata.json b/delta/plugins/blazegraph/src/test/resources/routes/responses/indexing-view-metadata.json index 3240cbbf9d..763d073f9b 100644 --- a/delta/plugins/blazegraph/src/test/resources/routes/responses/indexing-view-metadata.json +++ b/delta/plugins/blazegraph/src/test/resources/routes/responses/indexing-view-metadata.json @@ -13,12 +13,12 @@ "_createdBy": "http://localhost/v1/realms/myrealm/users/Bob", "_uuid": "{{uuid}}", "_deprecated": {{deprecated}}, - "_incoming": "http://localhost/v1/views/org/proj/indexing-view/incoming", - "_outgoing": "http://localhost/v1/views/org/proj/indexing-view/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/org/proj", "_rev": {{rev}}, "_indexingRev": {{indexingRev}}, - "_self": "http://localhost/v1/views/org/proj/indexing-view", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/realms/myrealm/users/Bob" } \ No newline at end of file diff --git a/delta/plugins/blazegraph/src/test/resources/routes/responses/indexing-view.json b/delta/plugins/blazegraph/src/test/resources/routes/responses/indexing-view.json index ad8fb1c3ab..f887c3d89e 100644 --- a/delta/plugins/blazegraph/src/test/resources/routes/responses/indexing-view.json +++ b/delta/plugins/blazegraph/src/test/resources/routes/responses/indexing-view.json @@ -12,12 +12,12 @@ "_createdAt": "1970-01-01T00:00:00Z", "_createdBy": "http://localhost/v1/realms/myrealm/users/Bob", "_deprecated": {{deprecated}}, - "_incoming": "http://localhost/v1/views/org/proj/indexing-view/incoming", - "_outgoing": "http://localhost/v1/views/org/proj/indexing-view/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/org/proj", "_rev": {{rev}}, "_indexingRev": {{indexingRev}}, - "_self": "http://localhost/v1/views/org/proj/indexing-view", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/realms/myrealm/users/Bob", "includeDeprecated": false, diff --git a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViewsGen.scala b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViewsGen.scala index 14f0924d68..5525feac5e 100644 --- a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViewsGen.scala +++ b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/BlazegraphViewsGen.scala @@ -2,9 +2,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.blazegraph import ch.epfl.bluebrain.nexus.delta.plugins.blazegraph.model.{BlazegraphViewState, BlazegraphViewValue, ViewResource} import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.sdk.model.Tags -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Subject} import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef import io.circe.Json @@ -25,9 +23,7 @@ object BlazegraphViewsGen { deprecated: Boolean = false, tags: Tags = Tags.empty, createdBy: Subject = Anonymous, - updatedBy: Subject = Anonymous, - am: ApiMappings = ApiMappings.empty, - base: Iri = nxv.base + updatedBy: Subject = Anonymous ): ViewResource = BlazegraphViewState( id, @@ -43,6 +39,5 @@ object BlazegraphViewsGen { createdBy, Instant.EPOCH, updatedBy - ) - .toResource(am, ProjectBase.unsafe(base)) + ).toResource } diff --git a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewRoutesFixtures.scala b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewRoutesFixtures.scala index ce94ca3d43..b01aef1851 100644 --- a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewRoutesFixtures.scala +++ b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewRoutesFixtures.scala @@ -98,9 +98,8 @@ trait BlazegraphViewRoutesFixtures ResourceUris.resource( projectRef, projectRef, - iri"http://example.com/id1", - ResourceRef(iri"http://example.com/someSchema") - )(project.apiMappings, project.base), + iri"http://example.com/id1" + ), 1, Set(iri"http://example.com/type1", iri"http://example.com/type2"), false, diff --git a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsQuerySpec.scala b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsQuerySpec.scala index 7af845b75c..a132b6b374 100644 --- a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsQuerySpec.scala +++ b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsQuerySpec.scala @@ -147,10 +147,7 @@ class BlazegraphViewsQuerySpec(docker: BlazegraphDocker) SparqlResourceLink( ResourceF( resourceId, - ResourceUris.resource(project1.ref, project1.ref, resourceId, ResourceRef(resourceId / "schema"))( - project1.apiMappings, - project1.base - ), + ResourceUris.resource(project1.ref, project1.ref, resourceId), 2, Set(resourceId / "type"), deprecated = false, diff --git a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsRoutesSpec.scala b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsRoutesSpec.scala index 54d5e17a83..6285b9fda2 100644 --- a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsRoutesSpec.scala +++ b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsRoutesSpec.scala @@ -20,6 +20,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress import ch.epfl.bluebrain.nexus.delta.sdk.directives.DeltaSchemeDirectives import ch.epfl.bluebrain.nexus.delta.sdk.fusion.FusionConfig import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ +import ch.epfl.bluebrain.nexus.delta.sdk.model.ResourceUris import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.events import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContextDummy import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolverContextResolution @@ -39,7 +40,8 @@ class BlazegraphViewsRoutesSpec extends BlazegraphViewRoutesFixtures { private val updatedIndexingSource = indexingSource.mapObject(_.add("resourceTag", Json.fromString("v1.5"))) - private val indexingViewId = nxv + "indexing-view" + private val indexingViewId = nxv + "indexing-view" + private val aggregateViewId = nxv + "aggregate-view" private val fetchContext = FetchContextDummy[BlazegraphViewRejection]( Map(project.ref -> project.context), @@ -99,20 +101,17 @@ class BlazegraphViewsRoutesSpec extends BlazegraphViewRoutesFixtures { .accepted Post("/v1/views/org/proj", indexingSource.toEntity) ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.Created - response.asJson shouldEqual jsonContentOf( - "routes/responses/indexing-view-metadata.json", - "uuid" -> uuid, - "rev" -> 1, - "indexingRev" -> 1, - "deprecated" -> false - ) + response.asJson shouldEqual indexingViewMetadata(1, 1, false) } } "create an aggregate view" in { Put("/v1/views/org/proj/aggregate-view", aggregateSource.toEntity) ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.Created - response.asJson shouldEqual jsonContentOf("routes/responses/aggregate-view-metadata.json") + response.asJson shouldEqual jsonContentOf( + "routes/responses/aggregate-view-metadata.json", + "self" -> ResourceUris("views", projectRef, aggregateViewId).accessUri + ) } } @@ -157,14 +156,7 @@ class BlazegraphViewsRoutesSpec extends BlazegraphViewRoutesFixtures { "update a view" in { Put("/v1/views/org/proj/indexing-view?rev=1", updatedIndexingSource.toEntity) ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf( - "routes/responses/indexing-view-metadata.json", - "uuid" -> uuid, - "rev" -> 2, - "indexingRev" -> 2, - "deprecated" -> false - ) - + response.asJson shouldEqual indexingViewMetadata(2, 2, false) } } "reject update of a view at a non-existent revision" in { @@ -179,13 +171,7 @@ class BlazegraphViewsRoutesSpec extends BlazegraphViewRoutesFixtures { val payload = json"""{"tag": "mytag", "rev": 1}""" Post("/v1/views/org/proj/indexing-view/tags?rev=2", payload.toEntity) ~> asBob ~> routes ~> check { status shouldEqual StatusCodes.Created - response.asJson shouldEqual jsonContentOf( - "routes/responses/indexing-view-metadata.json", - "uuid" -> uuid, - "rev" -> 3, - "indexingRev" -> 2, - "deprecated" -> false - ) + response.asJson shouldEqual indexingViewMetadata(3, 2, false) } } @@ -204,14 +190,7 @@ class BlazegraphViewsRoutesSpec extends BlazegraphViewRoutesFixtures { "deprecate a view" in { Delete("/v1/views/org/proj/indexing-view?rev=3") ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf( - "routes/responses/indexing-view-metadata.json", - "uuid" -> uuid, - "rev" -> 4, - "indexingRev" -> 2, - "deprecated" -> true - ) - + response.asJson shouldEqual indexingViewMetadata(4, 2, true) } } @@ -233,13 +212,7 @@ class BlazegraphViewsRoutesSpec extends BlazegraphViewRoutesFixtures { "fetch a view" in { Get("/v1/views/org/proj/indexing-view") ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf( - "routes/responses/indexing-view.json", - "uuid" -> uuid, - "deprecated" -> true, - "rev" -> 4, - "indexingRev" -> 2 - ) + response.asJson shouldEqual indexingView(4, 2, true) } } "fetch a view by rev or tag" in { @@ -254,13 +227,7 @@ class BlazegraphViewsRoutesSpec extends BlazegraphViewRoutesFixtures { forAll(endpoints) { endpoint => Get(endpoint) ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf( - "routes/responses/indexing-view.json", - "uuid" -> uuid, - "deprecated" -> false, - "rev" -> 1, - "indexingRev" -> 1 - ).mapObject(_.remove("resourceTag")) + response.asJson shouldEqual indexingView(1, 1, false).mapObject(_.remove("resourceTag")) } } @@ -366,4 +333,24 @@ class BlazegraphViewsRoutesSpec extends BlazegraphViewRoutesFixtures { } } } + + private def indexingViewMetadata(rev: Int, indexingRev: Int, deprecated: Boolean) = + jsonContentOf( + "routes/responses/indexing-view-metadata.json", + "uuid" -> uuid, + "deprecated" -> deprecated, + "rev" -> rev, + "indexingRev" -> indexingRev, + "self" -> ResourceUris("views", projectRef, indexingViewId).accessUri + ) + + private def indexingView(rev: Int, indexingRev: Int, deprecated: Boolean) = + jsonContentOf( + "routes/responses/indexing-view.json", + "uuid" -> uuid, + "deprecated" -> deprecated, + "rev" -> rev, + "indexingRev" -> indexingRev, + "self" -> ResourceUris("views", projectRef, indexingViewId).accessUri + ) } diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViews.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViews.scala index 088844dc7c..f6b08bcfab 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViews.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViews.scala @@ -25,7 +25,6 @@ import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegmentRef.{Latest, Revision, T import ch.epfl.bluebrain.nexus.delta.sdk.model._ import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchResults import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchResults.UnscoredSearchResults -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectContext import ch.epfl.bluebrain.nexus.delta.sdk.projects.{FetchContext, Projects} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolverContextResolution import ch.epfl.bluebrain.nexus.delta.sdk.views.IndexingRev @@ -82,7 +81,7 @@ final class CompositeViews private ( for { pc <- fetchContext.onCreate(project) iri <- expandIri(id, pc) - res <- eval(CreateCompositeView(iri, project, value, value.toJson(iri), subject, pc.base), pc) + res <- eval(CreateCompositeView(iri, project, value, value.toJson(iri), subject, pc.base)) } yield res }.span("createCompositeView") @@ -101,7 +100,7 @@ final class CompositeViews private ( for { pc <- fetchContext.onCreate(project) (iri, value) <- sourceDecoder(project, pc, source) - res <- eval(CreateCompositeView(iri, project, value, source.removeAllKeys("token"), caller.subject, pc.base), pc) + res <- eval(CreateCompositeView(iri, project, value, source.removeAllKeys("token"), caller.subject, pc.base)) } yield res }.span("createCompositeView") @@ -124,7 +123,7 @@ final class CompositeViews private ( iri <- expandIri(id, pc) viewValue <- sourceDecoder(project, pc, iri, source) res <- - eval(CreateCompositeView(iri, project, viewValue, source.removeAllKeys("token"), caller.subject, pc.base), pc) + eval(CreateCompositeView(iri, project, viewValue, source.removeAllKeys("token"), caller.subject, pc.base)) } yield res }.span("createCompositeView") @@ -155,7 +154,7 @@ final class CompositeViews private ( pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) source = value.toJson(iri) - res <- eval(UpdateCompositeView(iri, project, rev, value, source, subject, pc.base), pc) + res <- eval(UpdateCompositeView(iri, project, rev, value, source, subject, pc.base)) } yield res }.span("updateCompositeView") @@ -182,8 +181,7 @@ final class CompositeViews private ( viewValue <- sourceDecoder(project, pc, iri, source) res <- eval( - UpdateCompositeView(iri, project, rev, viewValue, source.removeAllKeys("token"), caller.subject, pc.base), - pc + UpdateCompositeView(iri, project, rev, viewValue, source.removeAllKeys("token"), caller.subject, pc.base) ) } yield res }.span("updateCompositeView") @@ -214,7 +212,7 @@ final class CompositeViews private ( for { pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) - res <- eval(TagCompositeView(iri, project, tagRev, tag, rev, subject), pc) + res <- eval(TagCompositeView(iri, project, tagRev, tag, rev, subject)) } yield res }.span("tagCompositeView") @@ -238,7 +236,7 @@ final class CompositeViews private ( for { pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) - res <- eval(DeprecateCompositeView(iri, project, rev, subject), pc) + res <- eval(DeprecateCompositeView(iri, project, rev, subject)) } yield res }.span("deprecateCompositeView") @@ -268,14 +266,12 @@ final class CompositeViews private ( * the view parent project */ def fetch(id: IdSegmentRef, project: ProjectRef): IO[CompositeViewRejection, ViewResource] = - fetchState(id, project).map { case (pc, state) => - state.toResource(pc.apiMappings, pc.base) - } + fetchState(id, project).map(_.toResource) def fetchState( id: IdSegmentRef, project: ProjectRef - ): IO[CompositeViewRejection, (ProjectContext, CompositeViewState)] = { + ): IO[CompositeViewRejection, CompositeViewState] = { for { pc <- fetchContext.onRead(project) iri <- expandIri(id.value, pc) @@ -287,7 +283,7 @@ final class CompositeViews private ( case Tag(_, tag) => log.stateOr(project, iri, tag, notFound, TagNotFound(tag)) } - } yield (pc, state) + } yield state }.span("fetchCompositeView") /** @@ -295,7 +291,7 @@ final class CompositeViews private ( */ def fetchIndexingView(id: IdSegmentRef, project: ProjectRef): IO[CompositeViewRejection, ActiveViewDef] = fetchState(id, project) - .flatMap { case (_, state) => + .flatMap { state => CompositeViewDef(state) match { case v: ActiveViewDef => IO.pure(v) case d: DeprecatedViewDef => IO.raiseError(ViewIsDeprecated(d.ref.viewId)) @@ -323,19 +319,9 @@ final class CompositeViews private ( params: CompositeViewSearchParams, ordering: Ordering[ViewResource] ): UIO[UnscoredSearchResults[ViewResource]] = { - val predicate = params.project.fold[Scope](Scope.Root)(ref => Scope.Project(ref)) + val scope = params.project.fold[Scope](Scope.Root)(ref => Scope.Project(ref)) SearchResults( - log.currentStates(predicate, identity(_)).evalMapFilter[Task, ViewResource] { state => - fetchContext.cacheOnReads - .onRead(state.project) - .redeemWith( - _ => UIO.none, - pc => { - val res = state.toResource(pc.apiMappings, pc.base) - params.matches(res).map(Option.when(_)(res)) - } - ) - }, + log.currentStates(scope, _.toResource).evalFilter(params.matches), pagination, ordering ).span("listCompositeViews") @@ -364,14 +350,8 @@ final class CompositeViews private ( CompositeViewDef(v) } - private def eval(cmd: CompositeViewCommand) = - log.evaluate(cmd.project, cmd.id, cmd) - - private def eval( - cmd: CompositeViewCommand, - pc: ProjectContext - ): IO[CompositeViewRejection, ViewResource] = - eval(cmd).map(_._2.toResource(pc.apiMappings, pc.base)) + private def eval(cmd: CompositeViewCommand): IO[CompositeViewRejection, ViewResource] = + log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource) } diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeView.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeView.scala index d10d01e7ee..c9dd433390 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeView.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeView.scala @@ -172,7 +172,7 @@ object CompositeView { ResourceShift.withMetadata[CompositeViewState, CompositeView, Metadata]( CompositeViews.entityType, (ref, project) => views.fetch(IdSegmentRef(ref), project), - (context, state) => state.toResource(context.apiMappings, context.base), + state => state.toResource, value => JsonLdContent(value, value.value.source, Some(value.value.metadata)) ) } diff --git a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewState.scala b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewState.scala index 517c30480a..a7afe90638 100644 --- a/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewState.scala +++ b/delta/plugins/composite-views/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/model/CompositeViewState.scala @@ -5,7 +5,6 @@ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.sdk.crypto.Crypto import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} @@ -80,10 +79,10 @@ final case class CompositeViewState( /** * Converts the state into a resource representation. */ - def toResource(mappings: ApiMappings, base: ProjectBase): ViewResource = + def toResource: ViewResource = ResourceF( id = id, - uris = ResourceUris("views", project, id)(mappings, base), + uris = ResourceUris("views", project, id), rev = rev, types = Set(nxv.View, compositeViewType), deprecated = deprecated, diff --git a/delta/plugins/composite-views/src/test/resources/routes/responses/view-metadata.json b/delta/plugins/composite-views/src/test/resources/routes/responses/view-metadata.json index cdf749740a..e4a0a49f00 100644 --- a/delta/plugins/composite-views/src/test/resources/routes/responses/view-metadata.json +++ b/delta/plugins/composite-views/src/test/resources/routes/responses/view-metadata.json @@ -13,11 +13,11 @@ "_createdBy": "http://localhost/v1/realms/myrealm/users/Bob", "_uuid": "{{uuid}}", "_deprecated": {{deprecated}}, - "_incoming": "http://localhost/v1/views/myorg/myproj/{{uuid}}/incoming", - "_outgoing": "http://localhost/v1/views/myorg/myproj/{{uuid}}/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/myorg/myproj", "_rev": {{rev}}, - "_self": "http://localhost/v1/views/myorg/myproj/{{uuid}}", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/realms/myrealm/users/Bob" } \ No newline at end of file diff --git a/delta/plugins/composite-views/src/test/resources/routes/responses/view.json b/delta/plugins/composite-views/src/test/resources/routes/responses/view.json index ca5f89b179..17b2a89e59 100644 --- a/delta/plugins/composite-views/src/test/resources/routes/responses/view.json +++ b/delta/plugins/composite-views/src/test/resources/routes/responses/view.json @@ -92,11 +92,11 @@ "_createdBy": "http://localhost/v1/realms/myrealm/users/Bob", "_uuid": "{{uuid}}", "_deprecated": {{deprecated}}, - "_incoming": "http://localhost/v1/views/myorg/myproj/{{uuid}}/incoming", - "_outgoing": "http://localhost/v1/views/myorg/myproj/{{uuid}}/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/myorg/myproj", "_rev": {{rev}}, - "_self": "http://localhost/v1/views/myorg/myproj/{{uuid}}", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/realms/myrealm/users/Bob" } \ No newline at end of file diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsGen.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsGen.scala index 6240ecdb3e..7a6beb68d8 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsGen.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsGen.scala @@ -4,8 +4,8 @@ import ch.epfl.bluebrain.nexus.delta.plugins.compositeviews.model._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.Project import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Subject} +import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef import io.circe.Json import java.time.Instant @@ -14,7 +14,7 @@ import java.util.UUID object CompositeViewsGen { def resourceFor( - project: Project, + project: ProjectRef, id: Iri, uuid: UUID, value: CompositeViewValue, @@ -29,7 +29,7 @@ object CompositeViewsGen { ): ViewResource = { ResourceF( id, - ResourceUris("views", project.ref, id)(project.apiMappings, project.base), + ResourceUris("views", project, id), rev, Set(nxv.View, compositeViewType), deprecated, @@ -40,7 +40,7 @@ object CompositeViewsGen { schema, CompositeView( id, - project.ref, + project, value.sources, value.projections, value.rebuildStrategy, diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsSpec.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsSpec.scala index 484055805c..47a97b864a 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsSpec.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/CompositeViewsSpec.scala @@ -81,7 +81,7 @@ class CompositeViewsSpec tags: Tags = Tags.empty, source: Json ): ViewResource = CompositeViewsGen.resourceFor( - project, + projectRef, id, uuid, value, diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsIndexingRoutesSpec.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsIndexingRoutesSpec.scala index 4f7423c663..543aaa58b5 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsIndexingRoutesSpec.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsIndexingRoutesSpec.scala @@ -46,7 +46,7 @@ class CompositeViewsIndexingRoutesSpec extends CompositeViewsRoutesFixtures { private val groupDirectives = DeltaSchemeDirectives(fetchContext, _ => UIO.none, _ => UIO.none) private val myId = nxv + "myid" - private val view = CompositeViewsGen.resourceFor(project, myId, uuid, viewValue, source = Json.obj()) + private val view = CompositeViewsGen.resourceFor(projectRef, myId, uuid, viewValue, source = Json.obj()) private val indexingView = ActiveViewDef( ViewRef(view.value.project, view.id), view.value.uuid, diff --git a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsRoutesSpec.scala b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsRoutesSpec.scala index c72eec414d..3883c51a7e 100644 --- a/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsRoutesSpec.scala +++ b/delta/plugins/composite-views/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/compositeviews/routes/CompositeViewsRoutesSpec.scala @@ -21,7 +21,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.circe.CirceMarshalling import ch.epfl.bluebrain.nexus.delta.sdk.directives.DeltaSchemeDirectives import ch.epfl.bluebrain.nexus.delta.sdk.fusion.FusionConfig import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ -import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegment +import ch.epfl.bluebrain.nexus.delta.sdk.model.{IdSegment, ResourceUris} import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.events import ch.epfl.bluebrain.nexus.delta.sdk.permissions.model.Permission import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContextDummy @@ -41,6 +41,7 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { events.read ) + private val viewId = nxv + uuid.toString private val esId = iri"http://example.com/es-projection" private val blazeId = iri"http://example.com/blazegraph-projection" @@ -110,12 +111,7 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { aclCheck.append(AclAddress.Root, caller.subject -> Set(permissions.write, permissions.read)).accepted Post("/v1/views/myorg/myproj", viewSource.toEntity) ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.Created - response.asJson shouldEqual jsonContentOf( - "routes/responses/view-metadata.json", - "uuid" -> uuid, - "rev" -> 1, - "deprecated" -> false - ) + response.asJson shouldEqual viewMetadata(1, false) } } @@ -136,12 +132,7 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { "update a view" in { Put(s"/v1/views/myorg/myproj/$uuid?rev=1", viewSourceUpdated.toEntity) ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf( - "routes/responses/view-metadata.json", - "uuid" -> uuid, - "rev" -> 2, - "deprecated" -> false - ) + response.asJson shouldEqual viewMetadata(2, false) } } @@ -156,12 +147,7 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { val payload = json"""{"tag": "mytag", "rev": 1}""" Post(s"/v1/views/myorg/myproj/$uuid/tags?rev=2", payload.toEntity) ~> asBob ~> routes ~> check { status shouldEqual StatusCodes.Created - response.asJson shouldEqual jsonContentOf( - "routes/responses/view-metadata.json", - "uuid" -> uuid, - "rev" -> 3, - "deprecated" -> false - ) + response.asJson shouldEqual viewMetadata(3, false) } } @@ -175,15 +161,7 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { "fetch a view" in { Get(s"/v1/views/myorg/myproj/$uuid") ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson should equalIgnoreArrayOrder( - jsonContentOf( - "routes/responses/view.json", - "uuid" -> uuid, - "deprecated" -> false, - "rev" -> 3, - "rebuildInterval" -> "2 minutes" - ) - ) + response.asJson should equalIgnoreArrayOrder(view(3, false, "2 minutes")) } } @@ -198,13 +176,8 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { Get(endpoint) ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.OK response.asJson should equalIgnoreArrayOrder( - jsonContentOf( - "routes/responses/view.json", - "uuid" -> uuid, - "deprecated" -> false, - "rev" -> 1, - "rebuildInterval" -> "1 minute" - ).mapObject(_.remove("resourceTag")) + view(1, false, "1 minute") + .mapObject(_.remove("resourceTag")) ) } } @@ -298,12 +271,7 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { "deprecate a view" in { Delete(s"/v1/views/myorg/myproj/$uuid?rev=3") ~> asBob ~> routes ~> check { response.status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf( - "routes/responses/view-metadata.json", - "uuid" -> uuid, - "rev" -> 4, - "deprecated" -> true - ) + response.asJson shouldEqual viewMetadata(4, true) } } @@ -327,7 +295,7 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { response.status shouldEqual StatusCodes.BadRequest response.asJson shouldEqual jsonContentOf( "routes/errors/view-deprecated.json", - "id" -> nxv.base / uuid.toString + "id" -> viewId ) } } @@ -347,7 +315,7 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { response.status shouldEqual StatusCodes.BadRequest response.asJson shouldEqual jsonContentOf( "routes/errors/view-deprecated.json", - "id" -> nxv.base / uuid.toString + "id" -> viewId ) } } @@ -362,4 +330,23 @@ class CompositeViewsRoutesSpec extends CompositeViewsRoutesFixtures { } } } + + private def viewMetadata(rev: Int, deprecated: Boolean) = + jsonContentOf( + "routes/responses/view-metadata.json", + "uuid" -> uuid, + "rev" -> rev, + "deprecated" -> deprecated, + "self" -> ResourceUris("views", projectRef, viewId).accessUri + ) + + private def view(rev: Int, deprecated: Boolean, rebuildInterval: String) = + jsonContentOf( + "routes/responses/view.json", + "uuid" -> uuid, + "deprecated" -> deprecated, + "rev" -> rev, + "rebuildInterval" -> rebuildInterval, + "self" -> ResourceUris("views", projectRef, viewId).accessUri + ) } diff --git a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViews.scala b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViews.scala index c802db0691..7254cfb18f 100644 --- a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViews.scala +++ b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViews.scala @@ -12,8 +12,8 @@ import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchVi import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchViewEvent._ import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchViewRejection._ import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchViewType.{AggregateElasticSearch, ElasticSearch} -import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchViewValue.{AggregateElasticSearchViewValue, IndexingElasticSearchViewValue} import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchViewValue.IndexingElasticSearchViewValue.nextIndexingRev +import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchViewValue.{AggregateElasticSearchViewValue, IndexingElasticSearchViewValue} import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.JsonLdApi @@ -23,7 +23,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.ExpandIri import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegmentRef.{Latest, Revision, Tag} import ch.epfl.bluebrain.nexus.delta.sdk.model._ import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectContext} +import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolverContextResolution import ch.epfl.bluebrain.nexus.delta.sourcing.ScopedEntityDefinition.Tagger import ch.epfl.bluebrain.nexus.delta.sourcing._ @@ -88,7 +88,7 @@ final class ElasticSearchViews private ( for { pc <- fetchContext.onCreate(project) iri <- expandIri(id, pc) - res <- eval(CreateElasticSearchView(iri, project, value, value.toJson(iri), subject), pc) + res <- eval(CreateElasticSearchView(iri, project, value, value.toJson(iri), subject)) } yield res }.span("createElasticSearchView") @@ -110,7 +110,7 @@ final class ElasticSearchViews private ( for { pc <- fetchContext.onCreate(project) (iri, value) <- sourceDecoder(project, pc, source) - res <- eval(CreateElasticSearchView(iri, project, value, source, caller.subject), pc) + res <- eval(CreateElasticSearchView(iri, project, value, source, caller.subject)) } yield res }.span("createElasticSearchView") @@ -134,7 +134,7 @@ final class ElasticSearchViews private ( pc <- fetchContext.onCreate(project) iri <- expandIri(id, pc) value <- sourceDecoder(project, pc, iri, source) - res <- eval(CreateElasticSearchView(iri, project, value, source, caller.subject), pc) + res <- eval(CreateElasticSearchView(iri, project, value, source, caller.subject)) } yield res }.span("createElasticSearchView") @@ -161,7 +161,7 @@ final class ElasticSearchViews private ( for { pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) - res <- eval(UpdateElasticSearchView(iri, project, rev, value, value.toJson(iri), subject), pc) + res <- eval(UpdateElasticSearchView(iri, project, rev, value, value.toJson(iri), subject)) } yield res }.span("updateElasticSearchView") @@ -189,7 +189,7 @@ final class ElasticSearchViews private ( pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) value <- sourceDecoder(project, pc, iri, source) - res <- eval(UpdateElasticSearchView(iri, project, rev, value, source, caller.subject), pc) + res <- eval(UpdateElasticSearchView(iri, project, rev, value, source, caller.subject)) } yield res }.span("updateElasticSearchView") @@ -219,7 +219,7 @@ final class ElasticSearchViews private ( for { pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) - res <- eval(TagElasticSearchView(iri, project, tagRev, tag, rev, subject), pc) + res <- eval(TagElasticSearchView(iri, project, tagRev, tag, rev, subject)) } yield res }.span("tagElasticSearchView") @@ -244,7 +244,7 @@ final class ElasticSearchViews private ( for { pc <- fetchContext.onModify(project) iri <- expandIri(id, pc) - res <- eval(DeprecateElasticSearchView(iri, project, rev, subject), pc) + res <- eval(DeprecateElasticSearchView(iri, project, rev, subject)) } yield res }.span("deprecateElasticSearchView") @@ -274,14 +274,14 @@ final class ElasticSearchViews private ( * the view parent project */ def fetch(id: IdSegmentRef, project: ProjectRef): IO[ElasticSearchViewRejection, ViewResource] = - fetchState(id, project).map { case (pc, state) => - state.toResource(pc.apiMappings, pc.base, defaultElasticsearchMapping, defaultElasticsearchSettings) + fetchState(id, project).map { state => + state.toResource(defaultElasticsearchMapping, defaultElasticsearchSettings) } def fetchState( id: IdSegmentRef, project: ProjectRef - ): IO[ElasticSearchViewRejection, (ProjectContext, ElasticSearchViewState)] = { + ): IO[ElasticSearchViewRejection, ElasticSearchViewState] = { for { pc <- fetchContext.onRead(project) iri <- expandIri(id.value, pc) @@ -293,7 +293,7 @@ final class ElasticSearchViews private ( case Tag(_, tag) => log.stateOr(project, iri, tag, notFound, TagNotFound(tag)) } - } yield (pc, state) + } yield state }.span("fetchElasticSearchView") /** @@ -309,7 +309,7 @@ final class ElasticSearchViews private ( project: ProjectRef ): IO[ElasticSearchViewRejection, ActiveViewDef] = fetchState(id, project) - .flatMap { case (_, state) => + .flatMap { state => IndexingViewDef(state, defaultElasticsearchMapping, defaultElasticsearchSettings, prefix) match { case Some(viewDef) => viewDef match { @@ -350,14 +350,10 @@ final class ElasticSearchViews private ( IndexingViewDef(v, defaultElasticsearchMapping, defaultElasticsearchSettings, prefix) } - private def eval(cmd: ElasticSearchViewCommand) = - log.evaluate(cmd.project, cmd.id, cmd) - - private def eval( - cmd: ElasticSearchViewCommand, - pc: ProjectContext - ): IO[ElasticSearchViewRejection, ViewResource] = - eval(cmd).map(_._2.toResource(pc.apiMappings, pc.base, defaultElasticsearchMapping, defaultElasticsearchSettings)) + private def eval(cmd: ElasticSearchViewCommand): IO[ElasticSearchViewRejection, ViewResource] = + log + .evaluate(cmd.project, cmd.id, cmd) + .map(_._2.toResource(defaultElasticsearchMapping, defaultElasticsearchSettings)) } object ElasticSearchViews { diff --git a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewsQuery.scala b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewsQuery.scala index 5af59cd570..ed47f021de 100644 --- a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewsQuery.scala +++ b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewsQuery.scala @@ -141,7 +141,7 @@ object ElasticSearchViewsQuery { ElasticSearchViews.entityType, ElasticSearchViewState.serializer, defaultViewId, - views.fetchState(_, _).map(_._2), + views.fetchState(_, _), view => IO.raiseWhen(view.deprecated)(ViewIsDeprecated(view.id)).as { view.value match { diff --git a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/model/ElasticSearchView.scala b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/model/ElasticSearchView.scala index 7905601824..e4b6e7bb0c 100644 --- a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/model/ElasticSearchView.scala +++ b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/model/ElasticSearchView.scala @@ -279,7 +279,7 @@ object ElasticSearchView { ResourceShift.withMetadata[ElasticSearchViewState, ElasticSearchView, Metadata]( ElasticSearchViews.entityType, (ref, project) => views.fetch(IdSegmentRef(ref), project), - (context, state) => state.toResource(context.apiMappings, context.base, defaultMapping, defaultSettings), + state => state.toResource(defaultMapping, defaultSettings), value => JsonLdContent(value, value.value.source, Some(value.value.metadata)) ) } diff --git a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/model/ElasticSearchViewState.scala b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/model/ElasticSearchViewState.scala index 2ad88516ec..d0d4b6e6a7 100644 --- a/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/model/ElasticSearchViewState.scala +++ b/delta/plugins/elasticsearch/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/model/ElasticSearchViewState.scala @@ -5,7 +5,6 @@ import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchVi import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.ElasticSearchViewValue._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} @@ -111,14 +110,12 @@ final case class ElasticSearchViewState( } def toResource( - mappings: ApiMappings, - base: ProjectBase, defaultMapping: JsonObject, defaultSettings: JsonObject ): ViewResource = { ResourceF( id = id, - uris = ResourceUris("views", project, id)(mappings, base), + uris = ResourceUris("views", project, id), rev = rev, types = types, deprecated = deprecated, diff --git a/delta/plugins/elasticsearch/src/test/resources/routes/elasticsearch-view-read-response.json b/delta/plugins/elasticsearch/src/test/resources/routes/elasticsearch-view-read-response.json index 72f60317c3..c05d2b38cd 100644 --- a/delta/plugins/elasticsearch/src/test/resources/routes/elasticsearch-view-read-response.json +++ b/delta/plugins/elasticsearch/src/test/resources/routes/elasticsearch-view-read-response.json @@ -12,12 +12,12 @@ "_createdAt" : "1970-01-01T00:00:00Z", "_createdBy" : "{{createdBy}}", "_deprecated" : {{deprecated}}, - "_incoming" : "http://localhost/v1/views/{{project}}/{{label}}/incoming", - "_outgoing" : "http://localhost/v1/views/{{project}}/{{label}}/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/{{project}}", "_rev" : {{rev}}, "_indexingRev": {{indexingRev}}, - "_self" : "http://localhost/v1/views/{{project}}/{{label}}", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "{{updatedBy}}", "_uuid" : "{{uuid}}", diff --git a/delta/plugins/elasticsearch/src/test/resources/routes/elasticsearch-view-write-response.json b/delta/plugins/elasticsearch/src/test/resources/routes/elasticsearch-view-write-response.json index 79c06e5b3b..4fd090022b 100644 --- a/delta/plugins/elasticsearch/src/test/resources/routes/elasticsearch-view-write-response.json +++ b/delta/plugins/elasticsearch/src/test/resources/routes/elasticsearch-view-write-response.json @@ -10,12 +10,12 @@ "_createdBy" : "{{createdBy}}", "_deprecated" : {{deprecated}}, "_uuid" : "{{uuid}}", - "_incoming" : "http://localhost/v1/views/{{project}}/{{label}}/incoming", - "_outgoing" : "http://localhost/v1/views/{{project}}/{{label}}/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/{{project}}", "_rev" : {{rev}}, "_indexingRev": {{indexingRev}}, - "_self" : "http://localhost/v1/views/{{project}}/{{label}}", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "{{updatedBy}}" } \ No newline at end of file diff --git a/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewGen.scala b/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewGen.scala index 7db1ec0f06..5d8690ab68 100644 --- a/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewGen.scala +++ b/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewGen.scala @@ -2,9 +2,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch import ch.epfl.bluebrain.nexus.delta.plugins.elasticsearch.model.{ElasticSearchViewState, ElasticSearchViewValue, ViewResource} import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.sdk.model.Tags -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Subject} import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef import io.circe.{Json, JsonObject} @@ -54,9 +52,7 @@ object ElasticSearchViewGen { deprecated: Boolean = false, tags: Tags = Tags.empty, createdBy: Subject = Anonymous, - updatedBy: Subject = Anonymous, - am: ApiMappings = ApiMappings.empty, - base: Iri = nxv.base + updatedBy: Subject = Anonymous ): ViewResource = stateFor( id, @@ -70,5 +66,5 @@ object ElasticSearchViewGen { tags, createdBy, updatedBy - ).toResource(am, ProjectBase.unsafe(base), JsonObject.empty, JsonObject.empty) + ).toResource(JsonObject.empty, JsonObject.empty) } diff --git a/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewsSpec.scala b/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewsSpec.scala index a8cfbbb045..409d31b355 100644 --- a/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewsSpec.scala +++ b/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/ElasticSearchViewsSpec.scala @@ -129,7 +129,7 @@ class ElasticSearchViewsSpec value, source, tags - ).toResource(project.apiMappings, project.base, defaultEsMapping, defaultEsSettings) + ).toResource(defaultEsMapping, defaultEsSettings) val viewId = iri"http://localhost/indexing" val aggregateViewId = iri"http://localhost/${genString()}" diff --git a/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/routes/ElasticSearchViewsRoutesSpec.scala b/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/routes/ElasticSearchViewsRoutesSpec.scala index 7a90149c1b..06b15e3123 100644 --- a/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/routes/ElasticSearchViewsRoutesSpec.scala +++ b/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/routes/ElasticSearchViewsRoutesSpec.scala @@ -15,6 +15,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress import ch.epfl.bluebrain.nexus.delta.sdk.directives.DeltaSchemeDirectives import ch.epfl.bluebrain.nexus.delta.sdk.fusion.FusionConfig import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ +import ch.epfl.bluebrain.nexus.delta.sdk.model.ResourceUris import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.events import ch.epfl.bluebrain.nexus.delta.sdk.projects.{FetchContext, FetchContextDummy} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolverContextResolution @@ -379,7 +380,7 @@ class ElasticSearchViewsRoutesSpec extends ElasticSearchViewsRoutesFixtures { "deprecated" -> deprecated, "createdBy" -> createdBy.asIri, "updatedBy" -> updatedBy.asIri, - "label" -> lastSegment(id) + "self" -> ResourceUris("views", projectRef, id).accessUri ) private def elasticSearchView( @@ -402,9 +403,6 @@ class ElasticSearchViewsRoutesSpec extends ElasticSearchViewsRoutesFixtures { "createdBy" -> createdBy.asIri, "updatedBy" -> updatedBy.asIri, "includeDeprecated" -> includeDeprecated, - "label" -> lastSegment(id) + "self" -> ResourceUris("views", projectRef, id).accessUri ).mapObject(_.add("settings", settings)) - - private def lastSegment(iri: Iri) = - iri.toString.substring(iri.toString.lastIndexOf("/") + 1) } diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/Files.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/Files.scala index 771f2b2221..d4ca770b2c 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/Files.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/Files.scala @@ -92,7 +92,7 @@ final class Files( _ <- test(CreateFile(iri, projectRef, testStorageRef, testStorageType, testAttributes, caller.subject)) (storageRef, storage) <- fetchActiveStorage(storageId, projectRef, pc) attributes <- extractFileAttributes(iri, entity, storage) - res <- eval(CreateFile(iri, projectRef, storageRef, storage.tpe, attributes, caller.subject), pc) + res <- eval(CreateFile(iri, projectRef, storageRef, storage.tpe, attributes, caller.subject)) } yield res }.span("createFile") @@ -120,7 +120,7 @@ final class Files( _ <- test(CreateFile(iri, projectRef, testStorageRef, testStorageType, testAttributes, caller.subject)) (storageRef, storage) <- fetchActiveStorage(storageId, projectRef, pc) attributes <- extractFileAttributes(iri, entity, storage) - res <- eval(CreateFile(iri, projectRef, storageRef, storage.tpe, attributes, caller.subject), pc) + res <- eval(CreateFile(iri, projectRef, storageRef, storage.tpe, attributes, caller.subject)) } yield res }.span("createFile") @@ -210,7 +210,7 @@ final class Files( _ <- test(UpdateFile(iri, projectRef, testStorageRef, testStorageType, testAttributes, rev, caller.subject)) (storageRef, storage) <- fetchActiveStorage(storageId, projectRef, pc) attributes <- extractFileAttributes(iri, entity, storage) - res <- eval(UpdateFile(iri, projectRef, storageRef, storage.tpe, attributes, rev, caller.subject), pc) + res <- eval(UpdateFile(iri, projectRef, storageRef, storage.tpe, attributes, rev, caller.subject)) } yield res }.span("updateFile") @@ -249,7 +249,7 @@ final class Files( resolvedFilename <- IO.fromOption(filename.orElse(path.lastSegment), InvalidFileLink(iri)) description <- FileDescription(resolvedFilename, mediaType) attributes <- LinkFile(storage).apply(path, description).mapError(LinkRejection(iri, storage.id, _)) - res <- eval(UpdateFile(iri, projectRef, storageRef, storage.tpe, attributes, rev, caller.subject), pc) + res <- eval(UpdateFile(iri, projectRef, storageRef, storage.tpe, attributes, rev, caller.subject)) } yield res }.span("updateLink") @@ -277,7 +277,7 @@ final class Files( for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(TagFile(iri, projectRef, tagRev, tag, rev, subject), pc) + res <- eval(TagFile(iri, projectRef, tagRev, tag, rev, subject)) } yield res }.span("tagFile") @@ -302,7 +302,7 @@ final class Files( for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(DeleteFileTag(iri, projectRef, tag, rev, subject), pc) + res <- eval(DeleteFileTag(iri, projectRef, tag, rev, subject)) } yield res }.span("deleteFileTag") @@ -324,7 +324,7 @@ final class Files( for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(DeprecateFile(iri, projectRef, rev, subject), pc) + res <- eval(DeprecateFile(iri, projectRef, rev, subject)) } yield res }.span("deprecateFile") @@ -371,7 +371,7 @@ final class Files( case Tag(_, tag) => log.stateOr(project, iri, tag, notFound, TagNotFound(tag)) } - } yield state.toResource(pc.apiMappings, pc.base) + } yield state.toResource }.span("fetchFile") private def createLink( @@ -389,11 +389,11 @@ final class Files( resolvedFilename <- IO.fromOption(filename.orElse(path.lastSegment), InvalidFileLink(iri)) description <- FileDescription(resolvedFilename, mediaType) attributes <- LinkFile(storage).apply(path, description).mapError(LinkRejection(iri, storage.id, _)) - res <- eval(CreateFile(iri, ref, storageRef, storage.tpe, attributes, caller.subject), pc) + res <- eval(CreateFile(iri, ref, storageRef, storage.tpe, attributes, caller.subject)) } yield res - private def eval(cmd: FileCommand, pc: ProjectContext): IO[FileRejection, FileResource] = - log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource(pc.apiMappings, pc.base)) + private def eval(cmd: FileCommand): IO[FileRejection, FileResource] = + log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource) private def test(cmd: FileCommand) = log.dryRun(cmd.project, cmd.id, cmd) diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/File.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/File.scala index a8c6075801..aa6c845783 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/File.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/File.scala @@ -61,7 +61,7 @@ object File { ResourceShift.apply[FileState, File]( Files.entityType, (ref, project) => files.fetch(IdSegmentRef(ref), project), - (context, state) => state.toResource(context.apiMappings, context.base), + state => state.toResource, value => JsonLdContent(value, value.value.asJson, None) ) diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/FileState.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/FileState.scala index 952e31c823..5b98b15b0d 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/FileState.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/model/FileState.scala @@ -4,7 +4,6 @@ import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.{nxvFile, schemas, Fi import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.model.StorageType import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ import ch.epfl.bluebrain.nexus.delta.plugins.storage.instances._ import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer @@ -76,10 +75,10 @@ final case class FileState( private def file: File = File(id, project, storage, storageType, attributes, tags) - def toResource(mappings: ApiMappings, base: ProjectBase): FileResource = + def toResource: FileResource = ResourceF( id = id, - uris = ResourceUris("files", project, id)(mappings, base), + uris = ResourceUris("files", project, id), rev = rev, types = types, deprecated = deprecated, diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/Storages.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/Storages.scala index 8829b57e79..115a8c9c3f 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/Storages.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/Storages.scala @@ -2,9 +2,9 @@ package ch.epfl.bluebrain.nexus.delta.plugins.storage.storages import cats.effect.Clock import cats.syntax.all._ +import ch.epfl.bluebrain.nexus.delta.kernel.Mapper import ch.epfl.bluebrain.nexus.delta.kernel.kamon.KamonMetricComponent import ch.epfl.bluebrain.nexus.delta.kernel.utils.{IOUtils, UUIDF} -import ch.epfl.bluebrain.nexus.delta.kernel.Mapper import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.Storages._ import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.StoragesConfig.StorageTypeConfig import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.model.StorageCommand._ @@ -24,13 +24,13 @@ import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegmentRef.{Latest, Revision, T import ch.epfl.bluebrain.nexus.delta.sdk.model._ import ch.epfl.bluebrain.nexus.delta.sdk.permissions.model.Permission import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectContext} +import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolverContextResolution import ch.epfl.bluebrain.nexus.delta.sourcing.ScopedEntityDefinition.Tagger import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.Tag.UserTag import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ElemStream, EntityType, ProjectRef, ResourceRef} -import ch.epfl.bluebrain.nexus.delta.sourcing.{Scope, ScopedEntityDefinition, ScopedEventLog, StateMachine, Transactors} +import ch.epfl.bluebrain.nexus.delta.sourcing._ import com.typesafe.scalalogging.Logger import fs2.Stream import io.circe.Json @@ -67,7 +67,7 @@ final class Storages private ( for { pc <- fetchContext.onCreate(projectRef) (iri, storageFields) <- sourceDecoder(projectRef, pc, source) - res <- eval(CreateStorage(iri, projectRef, storageFields, source, caller.subject), pc) + res <- eval(CreateStorage(iri, projectRef, storageFields, source, caller.subject)) _ <- unsetPreviousDefaultIfRequired(projectRef, res) } yield res }.span("createStorage") @@ -91,7 +91,7 @@ final class Storages private ( pc <- fetchContext.onCreate(projectRef) iri <- expandIri(id, pc) storageFields <- sourceDecoder(projectRef, pc, iri, source) - res <- eval(CreateStorage(iri, projectRef, storageFields, source, caller.subject), pc) + res <- eval(CreateStorage(iri, projectRef, storageFields, source, caller.subject)) _ <- unsetPreviousDefaultIfRequired(projectRef, res) } yield res }.span("createStorage") @@ -115,7 +115,7 @@ final class Storages private ( pc <- fetchContext.onCreate(projectRef) iri <- expandIri(id, pc) source = storageFields.toJson(iri) - res <- eval(CreateStorage(iri, projectRef, storageFields, source, caller.subject), pc) + res <- eval(CreateStorage(iri, projectRef, storageFields, source, caller.subject)) _ <- unsetPreviousDefaultIfRequired(projectRef, res) } yield res }.span("createStorage") @@ -151,7 +151,7 @@ final class Storages private ( pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) storageFields <- sourceDecoder(projectRef, pc, iri, source) - res <- eval(UpdateStorage(iri, projectRef, storageFields, source, rev, caller.subject), pc) + res <- eval(UpdateStorage(iri, projectRef, storageFields, source, rev, caller.subject)) _ <- IO.when(unsetPreviousDefault)(unsetPreviousDefaultIfRequired(projectRef, res)) } yield res }.span("updateStorage") @@ -178,7 +178,7 @@ final class Storages private ( pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) source = storageFields.toJson(iri) - res <- eval(UpdateStorage(iri, projectRef, storageFields, source, rev, caller.subject), pc) + res <- eval(UpdateStorage(iri, projectRef, storageFields, source, rev, caller.subject)) _ <- unsetPreviousDefaultIfRequired(projectRef, res) } yield res }.span("updateStorage") @@ -207,7 +207,7 @@ final class Storages private ( for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(TagStorage(iri, projectRef, tagRev, tag, rev, subject), pc) + res <- eval(TagStorage(iri, projectRef, tagRev, tag, rev, subject)) } yield res }.span("tagStorage") @@ -229,25 +229,10 @@ final class Storages private ( for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(DeprecateStorage(iri, projectRef, rev, subject), pc) + res <- eval(DeprecateStorage(iri, projectRef, rev, subject)) } yield res }.span("deprecateStorage") - /** - * Deprecate a view without applying preliminary checks on the project status - * - * @param id - * the storage identifier to expand as the id of the storage - * @param project - * the project where the storage belongs - * @param rev - * the current revision of the storage - */ - private[storages] def internalDeprecate(id: Iri, project: ProjectRef, rev: Int)(implicit - subject: Subject - ): IO[StorageRejection, Unit] = - eval(DeprecateStorage(id, project, rev, subject)).void - /** * Fetch the storage using the ''resourceRef'' * @@ -282,13 +267,11 @@ final class Storages private ( case Tag(_, tag) => log.stateOr(project, iri, tag, notFound, TagNotFound(tag)) } - } yield state.toResource(pc.apiMappings, pc.base) + } yield state.toResource }.span("fetchStorage") - private def fetchDefaults(project: ProjectRef): IO[StorageFetchRejection, Stream[Task, StorageResource]] = - fetchContext.onRead(project).map { pc => - log.currentStates(Scope.Project(project), _.toResource(pc.apiMappings, pc.base)).filter(_.value.default) - } + private def fetchDefaults(project: ProjectRef): Stream[Task, StorageResource] = + log.currentStates(Scope.Project(project), _.toResource).filter(_.value.default) /** * Fetches the default storage for a project. @@ -298,8 +281,7 @@ final class Storages private ( */ def fetchDefault(project: ProjectRef): IO[StorageRejection, StorageResource] = { for { - defaults <- fetchDefaults(project) - defaultOpt <- defaults.reduce(updatedByDesc.min(_, _)).head.compile.last.hideErrors + defaultOpt <- fetchDefaults(project).reduce(updatedByDesc.min(_, _)).head.compile.last.hideErrors default <- IO.fromOption(defaultOpt, DefaultStorageNotFound(project)) } yield default }.span("fetchDefaultStorage") @@ -316,31 +298,27 @@ final class Storages private ( project: ProjectRef, current: StorageResource ) = - IO.when(current.value.default)( - fetchDefaults(project).map(_.filter(_.id != current.id)).flatMap { resources => - resources - .evalTap { storage => - val source = - storage.value.source.replace("default" -> true, false).replace("default" -> "true", false) - val io = update(storage.id, project, storage.rev, source, unsetPreviousDefault = false)( - serviceAccount.caller - ) - logFailureAndContinue(io) - } - .compile - .drain - .hideErrors >> UIO.unit - } - ) + IO.when(current.value.default) { + fetchDefaults(project) + .filter(_.id != current.id) + .evalTap { storage => + val source = + storage.value.source.replace("default" -> true, false).replace("default" -> "true", false) + val io = update(storage.id, project, storage.rev, source, unsetPreviousDefault = false)( + serviceAccount.caller + ) + logFailureAndContinue(io) + } + .compile + .drain + .hideErrors >> UIO.unit + } private def logFailureAndContinue[A](io: IO[StorageRejection, A]): UIO[Unit] = io.mapError(err => logger.warn(err.reason)).attempt >> UIO.unit - private def eval(cmd: StorageCommand) = - log.evaluate(cmd.project, cmd.id, cmd) - - private def eval(cmd: StorageCommand, pc: ProjectContext): IO[StorageRejection, StorageResource] = - eval(cmd).map(_._2.toResource(pc.apiMappings, pc.base)) + private def eval(cmd: StorageCommand): IO[StorageRejection, StorageResource] = + log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource) } object Storages { diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/Storage.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/Storage.scala index 5a4ca546d3..f958ad7bc9 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/Storage.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/Storage.scala @@ -178,7 +178,7 @@ object Storage { ResourceShift.withMetadata[StorageState, Storage, Metadata]( Storages.entityType, (ref, project) => storages.fetch(IdSegmentRef(ref), project), - (context, state) => state.toResource(context.apiMappings, context.base), + state => state.toResource, value => JsonLdContent(value, value.value.source, Some(value.value.metadata)) ) diff --git a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageState.scala b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageState.scala index 676b10ec35..0ed5a8b001 100644 --- a/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageState.scala +++ b/delta/plugins/storage/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/model/StorageState.scala @@ -5,7 +5,6 @@ import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.model.StorageValue import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.{schemas, StorageResource} import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.ResourceRef.Latest @@ -69,10 +68,10 @@ final case class StorageState( case value: RemoteDiskStorageValue => RemoteDiskStorage(id, project, value, tags, source) } - def toResource(mappings: ApiMappings, base: ProjectBase): StorageResource = + def toResource: StorageResource = ResourceF( id = id, - uris = ResourceUris("storages", project, id)(mappings, base), + uris = ResourceUris("storages", project, id), rev = rev, types = value.tpe.types, deprecated = deprecated, diff --git a/delta/plugins/storage/src/test/resources/files/errors/unsupported-operation.json b/delta/plugins/storage/src/test/resources/files/errors/unsupported-operation.json index 51e3973b03..3546407291 100644 --- a/delta/plugins/storage/src/test/resources/files/errors/unsupported-operation.json +++ b/delta/plugins/storage/src/test/resources/files/errors/unsupported-operation.json @@ -1,6 +1,6 @@ { "@context" : "https://bluebrain.github.io/nexus/contexts/error.json", "@type" : "UnsupportedOperation", - "reason" : "File '{{id}}' could not be linked using storage '{{storage}}'", + "reason" : "File '{{id}}' could not be linked using storage '{{storageId}}'", "details" : "Moving a file is not supported for storages of type 'https://bluebrain.github.io/nexus/vocabulary/DiskStorage'" } diff --git a/delta/plugins/storage/src/test/resources/files/file-route-metadata-response.json b/delta/plugins/storage/src/test/resources/files/file-route-metadata-response.json index 97aad9160f..b5b7c82e6a 100644 --- a/delta/plugins/storage/src/test/resources/files/file-route-metadata-response.json +++ b/delta/plugins/storage/src/test/resources/files/file-route-metadata-response.json @@ -22,11 +22,11 @@ "_origin": "{{origin}}", "_mediaType": "{{mediaType}}", "_deprecated" : {{deprecated}}, - "_incoming" : "http://localhost/v1/files/{{project}}/{{label}}/incoming", - "_outgoing" : "http://localhost/v1/files/{{project}}/{{label}}/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/{{project}}", "_rev" : {{rev}}, - "_self" : "http://localhost/v1/files/{{project}}/{{label}}", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "{{updatedBy}}", "_uuid": "{{uuid}}" diff --git a/delta/plugins/storage/src/test/resources/storages/remote-storage-fetched.json b/delta/plugins/storage/src/test/resources/storages/remote-storage-fetched.json index 945af5971d..029cf12fa5 100644 --- a/delta/plugins/storage/src/test/resources/storages/remote-storage-fetched.json +++ b/delta/plugins/storage/src/test/resources/storages/remote-storage-fetched.json @@ -12,11 +12,11 @@ "_createdAt" : "1970-01-01T00:00:00Z", "_createdBy" : "http://localhost/v1/realms/wonderland/users/alice", "_deprecated" : false, - "_incoming" : "http://localhost/v1/storages/myorg/myproject/remote-disk-storage/incoming", - "_outgoing" : "http://localhost/v1/storages/myorg/myproject/remote-disk-storage/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/myorg/myproject", "_rev" : 1, - "_self" : "http://localhost/v1/storages/myorg/myproject/remote-disk-storage", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "http://localhost/v1/realms/wonderland/users/alice", "_algorithm" : "SHA-256", diff --git a/delta/plugins/storage/src/test/resources/storages/s3-storage-fetched.json b/delta/plugins/storage/src/test/resources/storages/s3-storage-fetched.json index 7c1a8a0f47..baf8b172ad 100644 --- a/delta/plugins/storage/src/test/resources/storages/s3-storage-fetched.json +++ b/delta/plugins/storage/src/test/resources/storages/s3-storage-fetched.json @@ -12,11 +12,11 @@ "_createdAt" : "1970-01-01T00:00:00Z", "_createdBy" : "http://localhost/v1/anonymous", "_deprecated" : true, - "_incoming" : "http://localhost/v1/storages/myorg/myproject/s3-storage/incoming", - "_outgoing" : "http://localhost/v1/storages/myorg/myproject/s3-storage/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/myorg/myproject", "_rev" : 5, - "_self" : "http://localhost/v1/storages/myorg/myproject/s3-storage", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "http://localhost/v1/anonymous", "_algorithm" : "SHA-256", diff --git a/delta/plugins/storage/src/test/resources/storages/storage-route-metadata-response.json b/delta/plugins/storage/src/test/resources/storages/storage-route-metadata-response.json index 30b86907bc..e06d27ce1c 100644 --- a/delta/plugins/storage/src/test/resources/storages/storage-route-metadata-response.json +++ b/delta/plugins/storage/src/test/resources/storages/storage-route-metadata-response.json @@ -10,11 +10,11 @@ "_createdBy" : "{{createdBy}}", "_deprecated" : {{deprecated}}, "_algorithm" : "{{algorithm}}", - "_incoming" : "http://localhost/v1/storages/{{project}}/{{label}}/incoming", - "_outgoing" : "http://localhost/v1/storages/{{project}}/{{label}}/outgoing", + "_incoming" : "{{self}}/incoming", + "_outgoing" : "{{self}}/outgoing", "_project" : "http://localhost/v1/projects/{{project}}", "_rev" : {{rev}}, - "_self" : "http://localhost/v1/storages/{{project}}/{{label}}", + "_self" : "{{self}}", "_updatedAt" : "1970-01-01T00:00:00Z", "_updatedBy" : "{{updatedBy}}" } \ No newline at end of file diff --git a/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/FileGen.scala b/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/FileGen.scala index 8d30607b1f..c6b63b13cc 100644 --- a/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/FileGen.scala +++ b/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/FileGen.scala @@ -3,9 +3,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.storage.files import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.{FileAttributes, FileState} import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.model.StorageType import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary import ch.epfl.bluebrain.nexus.delta.sdk.model.Tags -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Subject} import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} @@ -51,11 +49,8 @@ object FileGen { deprecated: Boolean = false, tags: Tags = Tags.empty, createdBy: Subject = Anonymous, - updatedBy: Subject = Anonymous, - am: ApiMappings = ApiMappings.empty, - base: Iri = Vocabulary.nxv.base + updatedBy: Subject = Anonymous ): FileResource = - state(id, project, storage, attributes, storageType, rev, deprecated, tags, createdBy, updatedBy) - .toResource(am, ProjectBase.unsafe(base)) + state(id, project, storage, attributes, storageType, rev, deprecated, tags, createdBy, updatedBy).toResource } diff --git a/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/routes/FilesRoutesSpec.scala b/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/routes/FilesRoutesSpec.scala index c581b46114..f02f0ac051 100644 --- a/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/routes/FilesRoutesSpec.scala +++ b/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/files/routes/FilesRoutesSpec.scala @@ -4,18 +4,20 @@ import akka.actor.typed import akka.http.scaladsl.model.ContentTypes.`text/plain(UTF-8)` import akka.http.scaladsl.model.MediaRanges._ import akka.http.scaladsl.model.MediaTypes.`text/html` -import akka.http.scaladsl.model.headers.{`Last-Event-ID`, Accept, Location, OAuth2BearerToken} +import akka.http.scaladsl.model.headers.{Accept, Location, OAuth2BearerToken} import akka.http.scaladsl.model.{StatusCodes, Uri} import akka.http.scaladsl.server.Route import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.Digest.ComputedDigest import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.model.{FileAttributes, FileRejection} import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.routes.FilesRoutesSpec.fileMetadata -import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.{permissions, FileFixtures, Files, FilesConfig} +import ch.epfl.bluebrain.nexus.delta.plugins.storage.files.{contexts => fileContexts, permissions, FileFixtures, Files, FilesConfig} import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.model.{StorageRejection, StorageStatEntry, StorageType} -import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.{permissions => storagesPermissions, StorageFixtures, Storages, StoragesConfig, StoragesStatistics} +import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.{contexts => storageContexts, permissions => storagesPermissions, StorageFixtures, Storages, StoragesConfig, StoragesStatistics} import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.RdfMediaTypes.`application/ld+json` +import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.{contexts, nxv} +import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, RemoteContextResolution} import ch.epfl.bluebrain.nexus.delta.sdk.IndexingAction import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclSimpleCheck import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress @@ -24,7 +26,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.http.HttpClient import ch.epfl.bluebrain.nexus.delta.sdk.identities.IdentitiesDummy import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.{Caller, ServiceAccount} import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ -import ch.epfl.bluebrain.nexus.delta.sdk.model.BaseUri +import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, ResourceUris} import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.events import ch.epfl.bluebrain.nexus.delta.sdk.permissions.model.Permission import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContextDummy @@ -36,16 +38,27 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Label, ProjectRef, Resource import ch.epfl.bluebrain.nexus.testkit._ import io.circe.Json import monix.bio.IO -import monix.execution.Scheduler import org.scalatest._ -@DoNotDiscover class FilesRoutesSpec extends BaseRouteSpec with CancelAfterFailure with StorageFixtures with FileFixtures { - implicit private val sc: Scheduler = Scheduler.global import akka.actor.typed.scaladsl.adapter._ implicit val typedSystem: typed.ActorSystem[Nothing] = system.toTyped - implicit val httpClient: HttpClient = HttpClient()(httpClientConfig, system, sc) + implicit val httpClient: HttpClient = HttpClient()(httpClientConfig, system, s) + + // TODO: sort out how we handle this in tests + implicit override def rcr: RemoteContextResolution = { + implicit val cl: ClassLoader = getClass.getClassLoader + RemoteContextResolution.fixed( + storageContexts.storages -> ContextValue.fromFile("/contexts/storages.json").accepted, + storageContexts.storagesMetadata -> ContextValue.fromFile("/contexts/storages-metadata.json").accepted, + fileContexts.files -> ContextValue.fromFile("/contexts/files.json").accepted, + Vocabulary.contexts.metadata -> ContextValue.fromFile("contexts/metadata.json").accepted, + Vocabulary.contexts.error -> ContextValue.fromFile("contexts/error.json").accepted, + Vocabulary.contexts.tags -> ContextValue.fromFile("contexts/tags.json").accepted, + Vocabulary.contexts.search -> ContextValue.fromFile("contexts/search.json").accepted + ) + } implicit private val caller: Caller = Caller(alice, Set(alice, Anonymous, Authenticated(realm), Group("group", realm))) @@ -83,7 +96,7 @@ class FilesRoutesSpec extends BaseRouteSpec with CancelAfterFailure with Storage IO.pure(allowedPerms.toSet), (_, _) => IO.unit, xas, - StoragesConfig(eventLogConfig, pagination, config), + StoragesConfig(eventLogConfig, pagination, stCfg), ServiceAccount(User("nexus-sa", Label.unsafe("sa"))) ).accepted lazy val files: Files = Files( @@ -143,7 +156,7 @@ class FilesRoutesSpec extends BaseRouteSpec with CancelAfterFailure with Storage Put("/v1/files/org/proj/file1", payload.toEntity) ~> routes ~> check { status shouldEqual StatusCodes.BadRequest response.asJson shouldEqual - jsonContentOf("files/errors/unsupported-operation.json", "id" -> file1, "storages" -> dId) + jsonContentOf("files/errors/unsupported-operation.json", "id" -> file1, "storageId" -> dId) } } @@ -216,7 +229,7 @@ class FilesRoutesSpec extends BaseRouteSpec with CancelAfterFailure with Storage Put("/v1/files/org/proj/file1?rev=3", payload.toEntity) ~> routes ~> check { status shouldEqual StatusCodes.BadRequest response.asJson shouldEqual - jsonContentOf("files/errors/unsupported-operation.json", "id" -> file1, "storages" -> dId) + jsonContentOf("files/errors/unsupported-operation.json", "id" -> file1, "storageId" -> dId) } } @@ -436,15 +449,6 @@ class FilesRoutesSpec extends BaseRouteSpec with CancelAfterFailure with Storage } } - "fail to get the events stream without events/read permission" in { - forAll(List("/v1/files/events", "/v1/files/myorg/events", "/v1/files/org/proj/events")) { endpoint => - Get(endpoint) ~> `Last-Event-ID`("2") ~> routes ~> check { - response.status shouldEqual StatusCodes.Forbidden - response.asJson shouldEqual jsonContentOf("errors/authorization-failed.json") - } - } - } - "redirect to fusion for the latest version if the Accept header is set to text/html" in { Get("/v1/files/org/project/file1") ~> Accept(`text/html`) ~> routes ~> check { response.status shouldEqual StatusCodes.SeeOther @@ -457,7 +461,7 @@ class FilesRoutesSpec extends BaseRouteSpec with CancelAfterFailure with Storage object FilesRoutesSpec extends TestHelpers with RouteFixtures { def fileMetadata( - ref: ProjectRef, + project: ProjectRef, id: Iri, attributes: FileAttributes, storage: ResourceRef.Revision, @@ -465,12 +469,11 @@ object FilesRoutesSpec extends TestHelpers with RouteFixtures { rev: Int = 1, deprecated: Boolean = false, createdBy: Subject = Anonymous, - updatedBy: Subject = Anonymous, - label: Option[String] = None + updatedBy: Subject = Anonymous )(implicit baseUri: BaseUri): Json = jsonContentOf( "files/file-route-metadata-response.json", - "project" -> ref, + "project" -> project, "id" -> id, "rev" -> rev, "storage" -> storage.iri, @@ -487,7 +490,7 @@ object FilesRoutesSpec extends TestHelpers with RouteFixtures { "createdBy" -> createdBy.asIri, "updatedBy" -> updatedBy.asIri, "type" -> storageType, - "label" -> label.fold(lastSegment(id))(identity) + "self" -> ResourceUris("files", project, id).accessUri ) } diff --git a/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/StorageGen.scala b/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/StorageGen.scala index 3a6b893233..0a0f6a2d5d 100644 --- a/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/StorageGen.scala +++ b/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/StorageGen.scala @@ -2,9 +2,7 @@ package ch.epfl.bluebrain.nexus.delta.plugins.storage.storages import ch.epfl.bluebrain.nexus.delta.plugins.storage.storages.model.{StorageState, StorageValue} import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.sdk.model.Tags -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Subject} import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef import io.circe.Json @@ -48,11 +46,8 @@ object StorageGen { deprecated: Boolean = false, tags: Tags = Tags.empty, createdBy: Subject = Anonymous, - updatedBy: Subject = Anonymous, - am: ApiMappings = ApiMappings.empty, - base: Iri = nxv.base + updatedBy: Subject = Anonymous ): StorageResource = - storageState(id, project, value, source, rev, deprecated, tags, createdBy, updatedBy) - .toResource(am, ProjectBase.unsafe(base)) + storageState(id, project, value, source, rev, deprecated, tags, createdBy, updatedBy).toResource } diff --git a/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/routes/StoragesRoutesSpec.scala b/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/routes/StoragesRoutesSpec.scala index 96dfe1d277..102f6dd907 100644 --- a/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/routes/StoragesRoutesSpec.scala +++ b/delta/plugins/storage/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/storage/storages/routes/StoragesRoutesSpec.scala @@ -22,6 +22,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.generators.ProjectGen import ch.epfl.bluebrain.nexus.delta.sdk.identities.IdentitiesDummy import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.{Caller, ServiceAccount} import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ +import ch.epfl.bluebrain.nexus.delta.sdk.model.ResourceUris import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.events import ch.epfl.bluebrain.nexus.delta.sdk.permissions.model.Permission import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContextDummy @@ -257,7 +258,10 @@ class StoragesRoutesSpec extends BaseRouteSpec with TryValues with StorageFixtur aclCheck.append(AclAddress.Root, Anonymous -> Set(permissions.read)).accepted Get("/v1/storages/myorg/myproject/s3-storage") ~> routes ~> check { status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf("storages/s3-storage-fetched.json") + response.asJson shouldEqual jsonContentOf( + "storages/s3-storage-fetched.json", + "self" -> self(s3Id) + ) } } @@ -277,7 +281,10 @@ class StoragesRoutesSpec extends BaseRouteSpec with TryValues with StorageFixtur forAll(List("rev=1", "tag=mytag")) { param => Get(s"$endpoint?$param") ~> routes ~> check { status shouldEqual StatusCodes.OK - response.asJson shouldEqual jsonContentOf("storages/remote-storage-fetched.json") + response.asJson shouldEqual jsonContentOf( + "storages/remote-storage-fetched.json", + "self" -> self(rdId) + ) } } } @@ -399,6 +406,8 @@ class StoragesRoutesSpec extends BaseRouteSpec with TryValues with StorageFixtur "updatedBy" -> updatedBy.asIri, "type" -> storageType, "algorithm" -> DigestAlgorithm.default, - "label" -> lastSegment(id) + "self" -> self(id) ) + + def self(id: Iri): Uri = ResourceUris("storages", projectRef, id).accessUri } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/ResourceShift.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/ResourceShift.scala index c07b213849..875bf2f102 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/ResourceShift.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/ResourceShift.scala @@ -3,16 +3,15 @@ package ch.epfl.bluebrain.nexus.delta.sdk import cats.syntax.all._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.{JsonLdApi, JsonLdJavaApi} +import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.JsonLdContext.keywords import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.RemoteContextResolution import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.encoder.JsonLdEncoder import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdContent import ch.epfl.bluebrain.nexus.delta.sdk.model.{BaseUri, ResourceF} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectContext -import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sdk.syntax._ +import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.{EntityType, ProjectRef, ResourceRef} import ch.epfl.bluebrain.nexus.delta.sourcing.offset.Offset -import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.JsonLdContext.keywords import ch.epfl.bluebrain.nexus.delta.sourcing.state.GraphResource import ch.epfl.bluebrain.nexus.delta.sourcing.state.State.ScopedState import ch.epfl.bluebrain.nexus.delta.sourcing.stream.Elem @@ -54,7 +53,7 @@ abstract class ResourceShift[State <: ScopedState, A, M]( implicit private val valueJsonLdEncoder: JsonLdEncoder[A] = valueEncoder implicit private val resourceFJsonLdEncoder: JsonLdEncoder[ResourceF[Unit]] = ResourceF.defaultResourceFAJsonLdEncoder - protected def toResourceF(context: ProjectContext, state: State): ResourceF[A] + protected def toResourceF(state: State): ResourceF[A] /** * Fetch the resource from its reference @@ -70,13 +69,12 @@ abstract class ResourceShift[State <: ScopedState, A, M]( /** * Retrieves a [[GraphResource]] from the json payload stored in database. */ - def toGraphResource(json: Json, fetchContext: ProjectRef => UIO[ProjectContext])(implicit + def toGraphResource(json: Json)(implicit cr: RemoteContextResolution ): Task[GraphResource] = for { state <- Task.fromEither(serializer.codec.decodeJson(json)) - context <- fetchContext(state.project) - resource = toResourceF(context, state) + resource = toResourceF(state) graph <- toGraphResource(state.project, resource) } yield graph @@ -145,7 +143,7 @@ object ResourceShift { def withMetadata[State <: ScopedState, A, M]( entityType: EntityType, fetchResource: (ResourceRef, ProjectRef) => IO[_, ResourceF[A]], - stateToResource: (ProjectContext, State) => ResourceF[A], + stateToResource: State => ResourceF[A], asContent: ResourceF[A] => JsonLdContent[A, M] )(implicit serializer: Serializer[_, State], @@ -160,8 +158,7 @@ object ResourceShift { Some(metadataEncoder) ) { - override protected def toResourceF(context: ProjectContext, state: State): ResourceF[A] = - stateToResource(context, state) + override protected def toResourceF(state: State): ResourceF[A] = stateToResource(state) override protected def resourceToContent(value: ResourceF[A]): JsonLdContent[A, M] = asContent(value) } @@ -184,7 +181,7 @@ object ResourceShift { def apply[State <: ScopedState, B]( entityType: EntityType, fetchResource: (ResourceRef, ProjectRef) => IO[_, ResourceF[B]], - stateToResource: (ProjectContext, State) => ResourceF[B], + stateToResource: State => ResourceF[B], asContent: ResourceF[B] => JsonLdContent[B, Nothing] )(implicit serializer: Serializer[_, State], @@ -197,8 +194,8 @@ object ResourceShift { valueEncoder, None ) { - override protected def toResourceF(context: ProjectContext, state: State): ResourceF[B] = - stateToResource(context, state) + override protected def toResourceF(state: State): ResourceF[B] = + stateToResource(state) override protected def resourceToContent(value: ResourceF[B]): JsonLdContent[B, Nothing] = asContent(value) } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/ResourceShifts.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/ResourceShifts.scala index 249fc001be..d3f64dd5f2 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/ResourceShifts.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/ResourceShifts.scala @@ -3,11 +3,10 @@ package ch.epfl.bluebrain.nexus.delta.sdk import cats.syntax.all._ import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.RemoteContextResolution import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdContent -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectContext -import ch.epfl.bluebrain.nexus.delta.sourcing.{EntityCheck, Transactors} import ch.epfl.bluebrain.nexus.delta.sourcing.implicits._ import ch.epfl.bluebrain.nexus.delta.sourcing.model.{EntityType, ProjectRef, ResourceRef} import ch.epfl.bluebrain.nexus.delta.sourcing.state.GraphResource +import ch.epfl.bluebrain.nexus.delta.sourcing.{EntityCheck, Transactors} import com.typesafe.scalalogging.Logger import io.circe.Json import monix.bio.{IO, Task, UIO} @@ -25,7 +24,7 @@ trait ResourceShifts { /** * Return a function to decode a json to a [[GraphResource]] according to its [[EntityType]] */ - def decodeGraphResource(fetchContext: ProjectRef => UIO[ProjectContext]): (EntityType, Json) => Task[GraphResource] + def decodeGraphResource: (EntityType, Json) => Task[GraphResource] } @@ -55,17 +54,16 @@ object ResourceShifts { resource <- shift.flatTraverse(_.fetch(reference, project)) } yield resource - override def decodeGraphResource( - fetchContext: ProjectRef => UIO[ProjectContext] - ): (EntityType, Json) => Task[GraphResource] = { (entityType: EntityType, json: Json) => - { - for { - shift <- findShift(entityType) - result <- shift.toGraphResource(json, fetchContext) - } yield result - }.tapError { err => - UIO.delay(logger.error(s"Entity of type '$entityType' could not be decoded as a graph resource", err)) - } + override def decodeGraphResource: (EntityType, Json) => Task[GraphResource] = { + (entityType: EntityType, json: Json) => + { + for { + shift <- findShift(entityType) + result <- shift.toGraphResource(json) + } yield result + }.tapError { err => + UIO.delay(logger.error(s"Entity of type '$entityType' could not be decoded as a graph resource", err)) + } } } } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/instances/ProjectRefInstances.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/instances/ProjectRefInstances.scala index 7492ad2b26..ace37f4e24 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/instances/ProjectRefInstances.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/instances/ProjectRefInstances.scala @@ -10,6 +10,6 @@ trait ProjectRefInstances { implicit final val projectRefIriEncoder: IriEncoder[ProjectRef] = new IriEncoder[ProjectRef] { override def apply(value: ProjectRef)(implicit base: BaseUri): Iri = - ResourceUris.project(value).accessUriShortForm.toIri + ResourceUris.project(value).accessUri.toIri } } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceF.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceF.scala index ecf744e74e..9de0ff83b4 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceF.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceF.scala @@ -86,8 +86,7 @@ final case class ResourceF[A]( * @return * the [[Iri]] resulting from resolving the self against the ''base'' */ - def self(implicit base: BaseUri): Iri = - uris.accessUriShortForm.toIri + def self(implicit base: BaseUri): Iri = uris.accessUri.toIri } object ResourceF { @@ -138,26 +137,26 @@ object ResourceF { implicit private def resourceUrisEncoder(implicit base: BaseUri): Encoder.AsObject[ResourceUris] = Encoder.AsObject.instance { case uris: RootResourceUris => - JsonObject("_self" -> uris.accessUriShortForm.asJson) + JsonObject("_self" -> uris.accessUri.asJson) case uris: ResourceInProjectUris => JsonObject( - "_self" -> uris.accessUriShortForm.asJson, + "_self" -> uris.accessUri.asJson, "_project" -> uris.project.asJson, - "_incoming" -> uris.incomingShortForm.asJson, - "_outgoing" -> uris.outgoingShortForm.asJson + "_incoming" -> uris.incoming.asJson, + "_outgoing" -> uris.outgoing.asJson ) case uris: EphemeralResourceInProjectUris => JsonObject( - "_self" -> uris.accessUriShortForm.asJson, + "_self" -> uris.accessUri.asJson, "_project" -> uris.project.asJson ) case uris: ResourceInProjectAndSchemaUris => JsonObject( - "_self" -> uris.accessUriShortForm.asJson, + "_self" -> uris.accessUri.asJson, "_project" -> uris.project.asJson, "_schemaProject" -> uris.schemaProject.asJson, - "_incoming" -> uris.incomingShortForm.asJson, - "_outgoing" -> uris.outgoingShortForm.asJson + "_incoming" -> uris.incoming.asJson, + "_outgoing" -> uris.outgoing.asJson ) } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceUris.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceUris.scala index c217bc297d..b3d53b4888 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceUris.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceUris.scala @@ -2,13 +2,9 @@ package ch.epfl.bluebrain.nexus.delta.sdk.model import akka.http.scaladsl.model.Uri import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, JsonLdContext} import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sdk.syntax._ -import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Label, ProjectRef, ResourceRef} - -import java.util.UUID +import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Label, ProjectRef} /** * Holds information about the different access Uri of a resource @@ -21,25 +17,12 @@ sealed trait ResourceUris extends Product with Serializable { */ def relativeAccessUri: Uri - /** - * @return - * the relative access [[Uri]] in a short form - */ - def relativeAccessUriShortForm: Uri - /** * @return * the access [[Uri]] */ def accessUri(implicit base: BaseUri): Uri = relativeAccessUri.resolvedAgainst(base.endpoint.finalSlash()) - - /** - * @return - * the access [[Uri]] in a short form - */ - def accessUriShortForm(implicit base: BaseUri): Uri = - relativeAccessUriShortForm.resolvedAgainst(base.endpoint.finalSlash()) } object ResourceUris { @@ -54,14 +37,11 @@ object ResourceUris { */ final case class ResourceInProjectUris( projectRef: ProjectRef, - relativeAccessUri: Uri, - relativeAccessUriShortForm: Uri + relativeAccessUri: Uri ) extends ResourceUris { - def incoming(implicit base: BaseUri): Uri = accessUri / "incoming" - def outgoing(implicit base: BaseUri): Uri = accessUri / "outgoing" - def incomingShortForm(implicit base: BaseUri): Uri = accessUriShortForm / "incoming" - def outgoingShortForm(implicit base: BaseUri): Uri = accessUriShortForm / "outgoing" - def project(implicit base: BaseUri): Uri = ResourceUris.project(projectRef).accessUri + def incoming(implicit base: BaseUri): Uri = accessUri / "incoming" + def outgoing(implicit base: BaseUri): Uri = accessUri / "outgoing" + def project(implicit base: BaseUri): Uri = ResourceUris.project(projectRef).accessUri } /** @@ -69,8 +49,7 @@ object ResourceUris { */ final case class EphemeralResourceInProjectUris( projectRef: ProjectRef, - relativeAccessUri: Uri, - relativeAccessUriShortForm: Uri + relativeAccessUri: Uri ) extends ResourceUris { def project(implicit base: BaseUri): Uri = ResourceUris.project(projectRef).accessUri } @@ -81,15 +60,12 @@ object ResourceUris { final case class ResourceInProjectAndSchemaUris( projectRef: ProjectRef, schemaProjectRef: ProjectRef, - relativeAccessUri: Uri, - relativeAccessUriShortForm: Uri + relativeAccessUri: Uri ) extends ResourceUris { - def incoming(implicit base: BaseUri): Uri = accessUri / "incoming" - def outgoing(implicit base: BaseUri): Uri = accessUri / "outgoing" - def incomingShortForm(implicit base: BaseUri): Uri = accessUriShortForm / "incoming" - def outgoingShortForm(implicit base: BaseUri): Uri = accessUriShortForm / "outgoing" - def project(implicit base: BaseUri): Uri = ResourceUris.project(projectRef).accessUri - def schemaProject(implicit base: BaseUri): Uri = ResourceUris.project(schemaProjectRef).accessUri + def incoming(implicit base: BaseUri): Uri = accessUri / "incoming" + def outgoing(implicit base: BaseUri): Uri = accessUri / "outgoing" + def project(implicit base: BaseUri): Uri = ResourceUris.project(projectRef).accessUri + def schemaProject(implicit base: BaseUri): Uri = ResourceUris.project(schemaProjectRef).accessUri } /** @@ -103,14 +79,9 @@ object ResourceUris { * @param id * the id that can be compacted */ - final def apply(resourceTypeSegment: String, projectRef: ProjectRef, id: Iri)( - mappings: ApiMappings, - base: ProjectBase - ): ResourceUris = { - val ctx = context(base, mappings) - val relative = Uri(resourceTypeSegment) / projectRef.organization.value / projectRef.project.value - val relativeShortForm = relative / ctx.compact(id, useVocab = false) - ResourceInProjectUris(projectRef, relative / id.toString, relativeShortForm) + final def apply(resourceTypeSegment: String, projectRef: ProjectRef, id: Iri): ResourceUris = { + val relative = Uri(resourceTypeSegment) / projectRef.organization.value / projectRef.project.value + ResourceInProjectUris(projectRef, relative / id.toString) } /** @@ -134,27 +105,18 @@ object ResourceUris { * the schema project reference * @param id * the id that can be compacted - * @param schema - * the schema reference that can be compacted */ private def apply( resourceTypeSegment: String, projectRef: ProjectRef, schemaProject: ProjectRef, - schema: ResourceRef, id: Iri - )( - mappings: ApiMappings, - base: ProjectBase ): ResourceUris = { - val ctx = context(base, mappings) - val relative = Uri(resourceTypeSegment) / projectRef.organization.value / projectRef.project.value - val relativeShortForm = relative / ctx.compact(schema.iri, useVocab = false) / ctx.compact(id, useVocab = false) + val relative = Uri(resourceTypeSegment) / projectRef.organization.value / projectRef.project.value ResourceInProjectAndSchemaUris( projectRef, schemaProject, - relative / schema.toString / id.toString, - relativeShortForm + relative / "_" / id.toString ) } @@ -192,32 +154,23 @@ object ResourceUris { def project(ref: ProjectRef): ResourceUris = apply(s"projects/$ref") - /** - * Resource uris for a project deletions - */ - def projectDeletes(ref: ProjectRef, uuid: UUID): ResourceUris = - apply(s"projects/$ref/deletions/$uuid") - /** * Resource uris for a resource */ - def resource(projectRef: ProjectRef, schemaProject: ProjectRef, id: Iri, schema: ResourceRef)( - mappings: ApiMappings, - base: ProjectBase - ): ResourceUris = - apply("resources", projectRef, schemaProject, schema, id)(mappings, base) + def resource(projectRef: ProjectRef, schemaProject: ProjectRef, id: Iri): ResourceUris = + apply("resources", projectRef, schemaProject, id) /** * Resource uris for a schema */ - def schema(ref: ProjectRef, id: Iri)(mappings: ApiMappings, base: ProjectBase): ResourceUris = - apply("schemas", ref, id)(mappings, base) + def schema(ref: ProjectRef, id: Iri): ResourceUris = + apply("schemas", ref, id) /** * Resource uris for a resolver */ - def resolver(ref: ProjectRef, id: Iri)(mappings: ApiMappings, base: ProjectBase): ResourceUris = - apply("resolvers", ref, id)(mappings, base) + def resolver(ref: ProjectRef, id: Iri): ResourceUris = + apply("resolvers", ref, id) /** * Resource uris for ephemeral resources that are scoped to a project. @@ -226,20 +179,9 @@ object ResourceUris { resourceTypeSegment: String, ref: ProjectRef, id: Iri - )(mappings: ApiMappings, base: ProjectBase): ResourceUris = { - val ctx = context(base, mappings) - val relative = Uri(resourceTypeSegment) / ref.organization.value / ref.project.value - val relativeAccess = relative / id.toString - val relativeShortForm = relative / ctx.compact(id, useVocab = false) - EphemeralResourceInProjectUris(ref, relativeAccess, relativeShortForm) + ): ResourceUris = { + val relative = Uri(resourceTypeSegment) / ref.organization.value / ref.project.value + val relativeAccess = relative / id.toString + EphemeralResourceInProjectUris(ref, relativeAccess) } - - private def context(base: ProjectBase, mappings: ApiMappings): JsonLdContext = - JsonLdContext( - ContextValue.empty, - base = Some(base.iri), - prefixMappings = mappings.prefixMappings.filterNot { case (_, iri) => iri == base.iri }, - aliases = mappings.aliases - ) - } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/projects/ProjectContextCache.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/projects/ProjectContextCache.scala deleted file mode 100644 index 84c1be15ec..0000000000 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/projects/ProjectContextCache.scala +++ /dev/null @@ -1,39 +0,0 @@ -package ch.epfl.bluebrain.nexus.delta.sdk.projects - -import ch.epfl.bluebrain.nexus.delta.kernel.cache.KeyValueStore -import ch.epfl.bluebrain.nexus.delta.sdk.error.ServiceError.FetchContextFailed -import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext.ContextRejection -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectContext -import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef -import com.typesafe.scalalogging.Logger -import monix.bio.{Task, UIO} - -import scala.concurrent.duration._ - -trait ProjectContextCache { - def fetchContext: ProjectRef => UIO[ProjectContext] -} - -object ProjectContextCache { - - private val logger: Logger = Logger[ProjectContextCache] - - def apply(fetchContext: FetchContext[ContextRejection]): Task[ProjectContextCache] = { - // TODO make the cache configurable - KeyValueStore.local[ProjectRef, ProjectContext](500, 2.minutes).map { kv => - def f(projectRef: ProjectRef): UIO[ProjectContext] = kv.getOrElseUpdate( - projectRef, - fetchContext - .onRead(projectRef) - .tapError { err => - Task.delay(logger.error(s"An error occurred while fetching the context for project '$projectRef': $err.")) - } - .hideErrorsWith(_ => FetchContextFailed(projectRef)) - ) - new ProjectContextCache { - override def fetchContext: ProjectRef => UIO[ProjectContext] = f - } - } - } - -} diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/projects/model/Project.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/projects/model/Project.scala index 389175f9f4..7b71a549a7 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/projects/model/Project.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/projects/model/Project.scala @@ -164,7 +164,7 @@ object Project { ResourceShift.withMetadata[ProjectState, Project, Metadata]( Projects.entityType, (_, ref) => projects.fetch(ref), - (_, state) => state.toResource(defaultMappings), + state => state.toResource(defaultMappings), value => JsonLdContent(value, value.value.asJson, Some(value.value.metadata)) ) diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImpl.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImpl.scala index e0beff4103..71f4b51567 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImpl.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImpl.scala @@ -2,6 +2,7 @@ package ch.epfl.bluebrain.nexus.delta.sdk.resolvers import cats.effect.Clock import ch.epfl.bluebrain.nexus.delta.kernel.kamon.KamonMetricComponent +import ch.epfl.bluebrain.nexus.delta.kernel.search.Pagination.FromPagination import ch.epfl.bluebrain.nexus.delta.kernel.utils.UUIDF import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.contexts @@ -11,13 +12,11 @@ import ch.epfl.bluebrain.nexus.delta.sdk.identities.model.Caller import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdSourceProcessor.JsonLdSourceResolvingDecoder import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegmentRef.{Latest, Revision, Tag} -import ch.epfl.bluebrain.nexus.delta.kernel.search.Pagination.FromPagination import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchParams.ResolverSearchParams import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchResults import ch.epfl.bluebrain.nexus.delta.sdk.model.search.SearchResults.UnscoredSearchResults import ch.epfl.bluebrain.nexus.delta.sdk.model.{IdSegment, IdSegmentRef} import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectContext import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.Resolvers.{entityType, expandIri} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolversImpl.ResolversLog import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverCommand.{CreateResolver, DeprecateResolver, TagResolver, UpdateResolver} @@ -28,7 +27,7 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.Tag.UserTag import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Identity, ProjectRef} import doobie.implicits._ import io.circe.Json -import monix.bio.{IO, Task, UIO} +import monix.bio.{IO, UIO} final class ResolversImpl private ( log: ResolversLog, @@ -45,7 +44,7 @@ final class ResolversImpl private ( for { pc <- fetchContext.onCreate(projectRef) (iri, resolverValue) <- sourceDecoder(projectRef, pc, source) - res <- eval(CreateResolver(iri, projectRef, resolverValue, source, caller), pc) + res <- eval(CreateResolver(iri, projectRef, resolverValue, source, caller)) } yield res }.span("createResolver") @@ -58,7 +57,7 @@ final class ResolversImpl private ( pc <- fetchContext.onCreate(projectRef) iri <- expandIri(id, pc) resolverValue <- sourceDecoder(projectRef, pc, iri, source) - res <- eval(CreateResolver(iri, projectRef, resolverValue, source, caller), pc) + res <- eval(CreateResolver(iri, projectRef, resolverValue, source, caller)) } yield res }.span("createResolver") @@ -71,7 +70,7 @@ final class ResolversImpl private ( pc <- fetchContext.onCreate(projectRef) iri <- expandIri(id, pc) source = ResolverValue.generateSource(iri, resolverValue) - res <- eval(CreateResolver(iri, projectRef, resolverValue, source, caller), pc) + res <- eval(CreateResolver(iri, projectRef, resolverValue, source, caller)) } yield res }.span("createResolver") @@ -85,7 +84,7 @@ final class ResolversImpl private ( pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) resolverValue <- sourceDecoder(projectRef, pc, iri, source) - res <- eval(UpdateResolver(iri, projectRef, resolverValue, source, rev, caller), pc) + res <- eval(UpdateResolver(iri, projectRef, resolverValue, source, rev, caller)) } yield res }.span("updateResolver") @@ -101,7 +100,7 @@ final class ResolversImpl private ( pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) source = ResolverValue.generateSource(iri, resolverValue) - res <- eval(UpdateResolver(iri, projectRef, resolverValue, source, rev, caller), pc) + res <- eval(UpdateResolver(iri, projectRef, resolverValue, source, rev, caller)) } yield res }.span("updateResolver") @@ -117,7 +116,7 @@ final class ResolversImpl private ( for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(TagResolver(iri, projectRef, tagRev, tag, rev, subject), pc) + res <- eval(TagResolver(iri, projectRef, tagRev, tag, rev, subject)) } yield res }.span("tagResolver") @@ -129,7 +128,7 @@ final class ResolversImpl private ( for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(DeprecateResolver(iri, projectRef, rev, subject), pc) + res <- eval(DeprecateResolver(iri, projectRef, rev, subject)) } yield res }.span("deprecateResolver") @@ -145,7 +144,7 @@ final class ResolversImpl private ( case Tag(_, tag) => log.stateOr(projectRef, iri, tag, notFound, TagNotFound(tag)) } - } yield state.toResource(pc.apiMappings, pc.base) + } yield state.toResource }.span("fetchResolver") def list( @@ -155,24 +154,14 @@ final class ResolversImpl private ( ): UIO[UnscoredSearchResults[ResolverResource]] = { val scope = params.project.fold[Scope](Scope.Root)(ref => Scope.Project(ref)) SearchResults( - log.currentStates(scope, identity(_)).evalMapFilter[Task, ResolverResource] { state => - fetchContext.cacheOnReads - .onRead(state.project) - .redeemWith( - _ => UIO.none, - pc => { - val res = state.toResource(pc.apiMappings, pc.base) - params.matches(res).map(Option.when(_)(res)) - } - ) - }, + log.currentStates(scope, _.toResource).evalFilter(params.matches), pagination, ordering ).span("listResolvers") } - private def eval(cmd: ResolverCommand, pc: ProjectContext): IO[ResolverRejection, ResolverResource] = - log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource(pc.apiMappings, pc.base)) + private def eval(cmd: ResolverCommand): IO[ResolverRejection, ResolverResource] = + log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource) } object ResolversImpl { diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/model/Resolver.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/model/Resolver.scala index ac630d35fe..a8f39b1446 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/model/Resolver.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/model/Resolver.scala @@ -105,7 +105,7 @@ object Resolver { ResourceShift.apply[ResolverState, Resolver]( Resolvers.entityType, (ref, project) => resolvers.fetch(IdSegmentRef(ref), project), - (context, state) => state.toResource(context.apiMappings, context.base), + state => state.toResource, value => JsonLdContent(value, value.value.source, None) ) diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/model/ResolverState.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/model/ResolverState.scala index 51fd62070e..e5e68b208d 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/model/ResolverState.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/model/ResolverState.scala @@ -4,7 +4,6 @@ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.schemas import ch.epfl.bluebrain.nexus.delta.sdk.ResolverResource import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.Resolver.{CrossProjectResolver, InProjectResolver} import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverValue.{CrossProjectValue, InProjectValue} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer @@ -83,10 +82,10 @@ final case class ResolverState( } } - def toResource(mappings: ApiMappings, base: ProjectBase): ResolverResource = + def toResource: ResolverResource = ResourceF( id = id, - uris = ResourceUris.resolver(project, id)(mappings, base), + uris = ResourceUris.resolver(project, id), rev = rev, types = value.tpe.types, deprecated = deprecated, diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesImpl.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesImpl.scala index 8366316874..406e550265 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesImpl.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesImpl.scala @@ -45,7 +45,7 @@ final class ResourcesImpl private ( projectContext <- fetchContext.onCreate(projectRef) schemeRef <- expandResourceRef(schema, projectContext) (iri, compacted, expanded) <- sourceParser(projectRef, projectContext, source) - res <- eval(CreateResource(iri, projectRef, schemeRef, source, compacted, expanded, caller), projectContext) + res <- eval(CreateResource(iri, projectRef, schemeRef, source, compacted, expanded, caller)) } yield res }.span("createResource") @@ -60,7 +60,7 @@ final class ResourcesImpl private ( iri <- expandIri(id, projectContext) schemeRef <- expandResourceRef(schema, projectContext) (compacted, expanded) <- sourceParser(projectRef, projectContext, iri, source) - res <- eval(CreateResource(iri, projectRef, schemeRef, source, compacted, expanded, caller), projectContext) + res <- eval(CreateResource(iri, projectRef, schemeRef, source, compacted, expanded, caller)) } yield res }.span("createResource") @@ -77,7 +77,7 @@ final class ResourcesImpl private ( schemeRefOpt <- expandResourceRef(schemaOpt, projectContext) (compacted, expanded) <- sourceParser(projectRef, projectContext, iri, source) res <- - eval(UpdateResource(iri, projectRef, schemeRefOpt, source, compacted, expanded, rev, caller), projectContext) + eval(UpdateResource(iri, projectRef, schemeRefOpt, source, compacted, expanded, rev, caller)) } yield res }.span("updateResource") @@ -93,7 +93,7 @@ final class ResourcesImpl private ( resource <- log.stateOr(projectRef, iri, ResourceNotFound(iri, projectRef, schemaRefOpt)) (compacted, expanded) <- sourceParser(projectRef, projectContext, iri, resource.source) res <- - eval(RefreshResource(iri, projectRef, schemaRefOpt, compacted, expanded, resource.rev, caller), projectContext) + eval(RefreshResource(iri, projectRef, schemaRefOpt, compacted, expanded, resource.rev, caller)) } yield res }.span("refreshResource") @@ -129,7 +129,7 @@ final class ResourcesImpl private ( projectContext <- fetchContext.onModify(projectRef) iri <- expandIri(id, projectContext) schemeRefOpt <- expandResourceRef(schemaOpt, projectContext) - res <- eval(TagResource(iri, projectRef, schemeRefOpt, tagRev, tag, rev, caller), projectContext) + res <- eval(TagResource(iri, projectRef, schemeRefOpt, tagRev, tag, rev, caller)) } yield res).span("tagResource") override def deleteTag( @@ -143,7 +143,7 @@ final class ResourcesImpl private ( projectContext <- fetchContext.onModify(projectRef) iri <- expandIri(id, projectContext) schemeRefOpt <- expandResourceRef(schemaOpt, projectContext) - res <- eval(DeleteResourceTag(iri, projectRef, schemeRefOpt, tag, rev, caller), projectContext) + res <- eval(DeleteResourceTag(iri, projectRef, schemeRefOpt, tag, rev, caller)) } yield res).span("deleteResourceTag") override def deprecate( @@ -156,7 +156,7 @@ final class ResourcesImpl private ( projectContext <- fetchContext.onModify(projectRef) iri <- expandIri(id, projectContext) schemeRefOpt <- expandResourceRef(schemaOpt, projectContext) - res <- eval(DeprecateResource(iri, projectRef, schemeRefOpt, rev, caller), projectContext) + res <- eval(DeprecateResource(iri, projectRef, schemeRefOpt, rev, caller)) } yield res).span("deprecateResource") override def fetch( @@ -177,11 +177,11 @@ final class ResourcesImpl private ( log.stateOr(projectRef, iri, tag, notFound, TagNotFound(tag)) } _ <- IO.raiseWhen(schemaRefOpt.exists(_.iri != state.schema.iri))(notFound) - } yield state.toResource(pc.apiMappings, pc.base) + } yield state.toResource }.span("fetchResource") - private def eval(cmd: ResourceCommand, pc: ProjectContext): IO[ResourceRejection, DataResource] = - log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource(pc.apiMappings, pc.base)) + private def eval(cmd: ResourceCommand): IO[ResourceRejection, DataResource] = + log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource) private def expandResourceRef(segment: IdSegment, context: ProjectContext): IO[InvalidResourceId, ResourceRef] = IO.fromOption( diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/Resource.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/Resource.scala index aa2cb86b53..4c51650779 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/Resource.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/Resource.scala @@ -68,7 +68,7 @@ object Resource { ResourceShift.apply[ResourceState, Resource]( Resources.entityType, (ref, project) => resources.fetch(IdSegmentRef(ref), project, None), - (context, state) => state.toResource(context.apiMappings, context.base), + state => state.toResource, value => JsonLdContent(value, value.value.source, None) ) } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/ResourceState.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/ResourceState.scala index 9408c89964..51312a5688 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/ResourceState.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/ResourceState.scala @@ -4,7 +4,6 @@ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.{CompactedJsonLd, ExpandedJsonLd} import ch.epfl.bluebrain.nexus.delta.sdk.DataResource import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} @@ -68,10 +67,10 @@ final case class ResourceState( updatedBy: Subject ) extends ScopedState { - def toResource(mappings: ApiMappings, base: ProjectBase): DataResource = + def toResource: DataResource = ResourceF( id = id, - uris = ResourceUris.resource(project, schemaProject, id, schema)(mappings, base), + uris = ResourceUris.resource(project, schemaProject, id), rev = rev, types = types, schema = schema, diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/SchemasImpl.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/SchemasImpl.scala index 8f26fe00fa..42e6f4ef6c 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/SchemasImpl.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/SchemasImpl.scala @@ -13,7 +13,6 @@ import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdSourceProcessor.JsonLdSour import ch.epfl.bluebrain.nexus.delta.sdk.model.IdSegmentRef.{Latest, Revision, Tag} import ch.epfl.bluebrain.nexus.delta.sdk.model._ import ch.epfl.bluebrain.nexus.delta.sdk.projects.FetchContext -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectContext import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.ResolverContextResolution import ch.epfl.bluebrain.nexus.delta.sdk.schemas.Schemas.{entityType, expandIri} import ch.epfl.bluebrain.nexus.delta.sdk.schemas.SchemasImpl.SchemasLog @@ -44,7 +43,7 @@ final class SchemasImpl private ( projectContext <- fetchContext.onCreate(projectRef) (iri, compacted, expanded) <- sourceParser(projectRef, projectContext, source) expandedResolved <- schemaImports.resolve(iri, projectRef, expanded.addType(nxv.Schema)) - res <- eval(CreateSchema(iri, projectRef, source, compacted, expandedResolved, caller.subject), projectContext) + res <- eval(CreateSchema(iri, projectRef, source, compacted, expandedResolved, caller.subject)) } yield res }.span("createSchema") @@ -58,7 +57,7 @@ final class SchemasImpl private ( iri <- expandIri(id, pc) (compacted, expanded) <- sourceParser(projectRef, pc, iri, source) expandedResolved <- schemaImports.resolve(iri, projectRef, expanded.addType(nxv.Schema)) - res <- eval(CreateSchema(iri, projectRef, source, compacted, expandedResolved, caller.subject), pc) + res <- eval(CreateSchema(iri, projectRef, source, compacted, expandedResolved, caller.subject)) } yield res }.span("createSchema") @@ -74,7 +73,7 @@ final class SchemasImpl private ( (compacted, expanded) <- sourceParser(projectRef, pc, iri, source) expandedResolved <- schemaImports.resolve(iri, projectRef, expanded.addType(nxv.Schema)) res <- - eval(UpdateSchema(iri, projectRef, source, compacted, expandedResolved, rev, caller.subject), pc) + eval(UpdateSchema(iri, projectRef, source, compacted, expandedResolved, rev, caller.subject)) } yield res }.span("updateSchema") @@ -89,7 +88,7 @@ final class SchemasImpl private ( (compacted, expanded) <- sourceParser(projectRef, pc, iri, schema.source) expandedResolved <- schemaImports.resolve(iri, projectRef, expanded.addType(nxv.Schema)) res <- - eval(RefreshSchema(iri, projectRef, compacted, expandedResolved, schema.rev, caller.subject), pc) + eval(RefreshSchema(iri, projectRef, compacted, expandedResolved, schema.rev, caller.subject)) } yield res }.span("refreshSchema") @@ -103,7 +102,7 @@ final class SchemasImpl private ( for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(TagSchema(iri, projectRef, tagRev, tag, rev, caller), pc) + res <- eval(TagSchema(iri, projectRef, tagRev, tag, rev, caller)) } yield res }.span("tagSchema") @@ -116,7 +115,7 @@ final class SchemasImpl private ( (for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(DeleteSchemaTag(iri, projectRef, tag, rev, caller), pc) + res <- eval(DeleteSchemaTag(iri, projectRef, tag, rev, caller)) } yield res).span("deleteSchemaTag") override def deprecate( @@ -127,7 +126,7 @@ final class SchemasImpl private ( (for { pc <- fetchContext.onModify(projectRef) iri <- expandIri(id, pc) - res <- eval(DeprecateSchema(iri, projectRef, rev, caller), pc) + res <- eval(DeprecateSchema(iri, projectRef, rev, caller)) } yield res).span("deprecateSchema") override def fetch(id: IdSegmentRef, projectRef: ProjectRef): IO[SchemaFetchRejection, SchemaResource] = { @@ -141,11 +140,11 @@ final class SchemasImpl private ( case Tag(_, tag) => log.stateOr(projectRef, iri, tag, SchemaNotFound(iri, projectRef), TagNotFound(tag)) } - } yield state.toResource(pc.apiMappings, pc.base) + } yield state.toResource }.span("fetchSchema") - private def eval(cmd: SchemaCommand, pc: ProjectContext): IO[SchemaRejection, SchemaResource] = - log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource(pc.apiMappings, pc.base)) + private def eval(cmd: SchemaCommand): IO[SchemaRejection, SchemaResource] = + log.evaluate(cmd.project, cmd.id, cmd).map(_._2.toResource) } object SchemasImpl { diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/Schema.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/Schema.scala index 91acb47d14..798468dfb3 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/Schema.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/Schema.scala @@ -93,7 +93,7 @@ object Schema { ResourceShift.apply[SchemaState, Schema]( Schemas.entityType, (ref, project) => schemas.fetch(IdSegmentRef(ref), project), - (context, state) => state.toResource(context.apiMappings, context.base), + state => state.toResource, value => JsonLdContent(value, value.value.source, None) ) diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/SchemaState.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/SchemaState.scala index 43f8d4ef49..15741bd8f8 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/SchemaState.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/SchemaState.scala @@ -6,7 +6,6 @@ import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.{nxv, schemas} import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.{CompactedJsonLd, ExpandedJsonLd} import ch.epfl.bluebrain.nexus.delta.sdk.SchemaResource import ch.epfl.bluebrain.nexus.delta.sdk.model.{ResourceF, ResourceUris, Tags} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sourcing.Serializer import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject import ch.epfl.bluebrain.nexus.delta.sourcing.model.ResourceRef.Latest @@ -74,10 +73,10 @@ final case class SchemaState( */ def types: Set[Iri] = Set(nxv.Schema) - def toResource(mappings: ApiMappings, base: ProjectBase): SchemaResource = + def toResource: SchemaResource = ResourceF( id = id, - uris = ResourceUris.schema(project, id)(mappings, base), + uris = ResourceUris.schema(project, id), rev = rev, types = types, schema = schema, @@ -94,9 +93,9 @@ object SchemaState { @nowarn("cat=unused") implicit val serializer: Serializer[Iri, SchemaState] = { - import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Database._ import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.CompactedJsonLd.Database._ import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.ExpandedJsonLd.Database._ + import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Database._ implicit val configuration: Configuration = Serializer.circeConfiguration implicit val codec: Codec.AsObject[SchemaState] = deriveConfiguredCodec[SchemaState] Serializer.dropNullsInjectType() diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/stream/GraphResourceStream.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/stream/GraphResourceStream.scala index 412c705d1c..74c7cd6ca9 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/stream/GraphResourceStream.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/stream/GraphResourceStream.scala @@ -1,7 +1,6 @@ package ch.epfl.bluebrain.nexus.delta.sdk.stream import ch.epfl.bluebrain.nexus.delta.sdk.ResourceShifts -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectContext import ch.epfl.bluebrain.nexus.delta.sourcing.Transactors import ch.epfl.bluebrain.nexus.delta.sourcing.config.QueryConfig import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ElemStream, ProjectRef, Tag} @@ -67,14 +66,13 @@ object GraphResourceStream { * Create a graph resource stream */ def apply( - fetchContext: ProjectRef => UIO[ProjectContext], qc: QueryConfig, xas: Transactors, shifts: ResourceShifts ): GraphResourceStream = new GraphResourceStream { override def continuous(project: ProjectRef, tag: Tag, start: Offset): ElemStream[GraphResource] = - StreamingQuery.elems(project, tag, start, qc, xas, shifts.decodeGraphResource(fetchContext)) + StreamingQuery.elems(project, tag, start, qc, xas, shifts.decodeGraphResource) override def currents(project: ProjectRef, tag: Tag, start: Offset): ElemStream[GraphResource] = StreamingQuery.elems( @@ -83,7 +81,7 @@ object GraphResourceStream { start, qc.copy(refreshStrategy = RefreshStrategy.Stop), xas, - shifts.decodeGraphResource(fetchContext) + shifts.decodeGraphResource ) override def remaining(project: ProjectRef, tag: Tag, start: Offset): UIO[Option[RemainingElems]] = diff --git a/delta/sdk/src/test/resources/resources/resource-with-context-and-metadata.json b/delta/sdk/src/test/resources/resources/resource-with-context-and-metadata.json index 62c4ca79c8..47e004f355 100644 --- a/delta/sdk/src/test/resources/resources/resource-with-context-and-metadata.json +++ b/delta/sdk/src/test/resources/resources/resource-with-context-and-metadata.json @@ -12,12 +12,12 @@ "_createdAt": "1970-01-01T00:00:00Z", "_createdBy": "http://localhost/v1/anonymous", "_deprecated": false, - "_incoming": "http://localhost/v1/resources/org/proj/_/testId/incoming", - "_outgoing": "http://localhost/v1/resources/org/proj/_/testId/outgoing", + "_incoming": "http://localhost/v1/resources/org/proj/_/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fvocabulary%2FtestId/incoming", + "_outgoing": "http://localhost/v1/resources/org/proj/_/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fvocabulary%2FtestId/outgoing", "_project": "http://localhost/v1/projects/org/proj", "_schemaProject": "http://localhost/v1/projects/org/proj", "_rev": 1, - "_self": "http://localhost/v1/resources/org/proj/_/testId", + "_self": "http://localhost/v1/resources/org/proj/_/https:%2F%2Fbluebrain.github.io%2Fnexus%2Fvocabulary%2FtestId", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/anonymous", "other:priority": 5, diff --git a/delta/sdk/src/test/resources/resources/resource-with-metadata.json b/delta/sdk/src/test/resources/resources/resource-with-metadata.json index b7b50df390..17b26f62c6 100644 --- a/delta/sdk/src/test/resources/resources/resource-with-metadata.json +++ b/delta/sdk/src/test/resources/resources/resource-with-metadata.json @@ -10,12 +10,12 @@ "_createdAt": "1970-01-01T00:00:00Z", "_createdBy": "http://localhost/v1/anonymous", "_deprecated": true, - "_incoming": "http://localhost/v1/resources/myorg/myproject/_/myid/incoming", - "_outgoing": "http://localhost/v1/resources/myorg/myproject/_/myid/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "http://localhost/v1/projects/myorg/myproject", "_rev": 10, "_schemaProject": "http://localhost/v1/projects/myorg/myproject", - "_self": "http://localhost/v1/resources/myorg/myproject/_/myid", + "_self": "{{self}}", "_updatedAt": "1970-01-01T00:00:00Z", "_updatedBy": "http://localhost/v1/anonymous" } \ No newline at end of file diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/ResolverGen.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/ResolverGen.scala index d6c42b68e7..c45e43710e 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/ResolverGen.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/ResolverGen.scala @@ -4,7 +4,6 @@ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.sdk.ResolverResource import ch.epfl.bluebrain.nexus.delta.sdk.model.Tags -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.Project import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.Resolver.InProjectResolver import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.ResolverValue.InProjectValue import ch.epfl.bluebrain.nexus.delta.sdk.resolvers.model.{Priority, ResolverState, ResolverValue} @@ -38,7 +37,7 @@ object ResolverGen { */ def resolverResourceFor( id: Iri, - project: Project, + project: ProjectRef, value: ResolverValue, source: Json, tags: Tags = Tags.empty, @@ -48,7 +47,7 @@ object ResolverGen { ): ResolverResource = ResolverState( id: Iri, - project.ref, + project, value, source, tags, @@ -58,8 +57,7 @@ object ResolverGen { subject, Instant.EPOCH, subject - ) - .toResource(project.apiMappings, project.base) + ).toResource /** * Generate a valid json source from resolver id and value diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/ResourceGen.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/ResourceGen.scala index 6ceb1ac7f3..e2bac00df2 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/ResourceGen.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/ResourceGen.scala @@ -1,19 +1,18 @@ package ch.epfl.bluebrain.nexus.delta.sdk.generators import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.{nxv, schemas} +import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.schemas import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.ExpandedJsonLd import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.{JsonLdApi, JsonLdJavaApi} import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.RemoteContextResolution import ch.epfl.bluebrain.nexus.delta.sdk.DataResource import ch.epfl.bluebrain.nexus.delta.sdk.jsonld.JsonLdContent import ch.epfl.bluebrain.nexus.delta.sdk.model.Tags -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sdk.resources.model.{Resource, ResourceState} import ch.epfl.bluebrain.nexus.delta.sdk.syntax._ import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Subject} -import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} import ch.epfl.bluebrain.nexus.delta.sourcing.model.ResourceRef.Latest +import ch.epfl.bluebrain.nexus.delta.sourcing.model.{ProjectRef, ResourceRef} import ch.epfl.bluebrain.nexus.testkit.IOValues import io.circe.Json @@ -76,9 +75,7 @@ object ResourceGen extends IOValues { tags: Tags = Tags.empty, rev: Int = 1, subject: Subject = Anonymous, - deprecated: Boolean = false, - am: ApiMappings = ApiMappings.empty, - base: Iri = nxv.base + deprecated: Boolean = false )(implicit resolution: RemoteContextResolution): DataResource = { val expanded = ExpandedJsonLd(source).accepted.replaceId(id) val compacted = expanded.toCompacted(source.topContextValueOrEmpty).accepted @@ -99,7 +96,7 @@ object ResourceGen extends IOValues { subject, Instant.EPOCH, subject - ).toResource(am, ProjectBase.unsafe(base)) + ).toResource } def resourceFor( @@ -107,9 +104,7 @@ object ResourceGen extends IOValues { types: Set[Iri] = Set.empty, rev: Int = 1, subject: Subject = Anonymous, - deprecated: Boolean = false, - am: ApiMappings = ApiMappings.empty, - base: Iri = nxv.base + deprecated: Boolean = false ): DataResource = ResourceState( resource.id, @@ -127,7 +122,7 @@ object ResourceGen extends IOValues { subject, Instant.EPOCH, subject - ).toResource(am, ProjectBase.unsafe(base)) + ).toResource def jsonLdContent(id: Iri, project: ProjectRef, source: Json)(implicit resolution: RemoteContextResolution) = { val resourceF = sourceToResourceF(id, project, source) diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/SchemaGen.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/SchemaGen.scala index be30c3573f..e2874a0834 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/SchemaGen.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/generators/SchemaGen.scala @@ -2,13 +2,11 @@ package ch.epfl.bluebrain.nexus.delta.sdk.generators import cats.data.NonEmptyList import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.ExpandedJsonLd import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.{JsonLdApi, JsonLdJavaApi} import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.RemoteContextResolution import ch.epfl.bluebrain.nexus.delta.sdk.SchemaResource import ch.epfl.bluebrain.nexus.delta.sdk.model.Tags -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} import ch.epfl.bluebrain.nexus.delta.sdk.schemas.model.{Schema, SchemaState} import ch.epfl.bluebrain.nexus.delta.sdk.syntax._ import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.{Anonymous, Subject} @@ -59,9 +57,7 @@ object SchemaGen extends IOValues with EitherValuable { schema: Schema, rev: Int = 1, subject: Subject = Anonymous, - deprecated: Boolean = false, - am: ApiMappings = ApiMappings.empty, - base: Iri = nxv.base + deprecated: Boolean = false ): SchemaResource = SchemaState( schema.id, @@ -76,6 +72,6 @@ object SchemaGen extends IOValues with EitherValuable { subject, Instant.EPOCH, subject - ).toResource(am, ProjectBase.unsafe(base)) + ).toResource } diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceFSpec.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceFSpec.scala index 633db6e4ed..93f09581e3 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceFSpec.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceFSpec.scala @@ -1,14 +1,12 @@ package ch.epfl.bluebrain.nexus.delta.sdk.model -import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.{nxv, schemas} -import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.acls +import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.sdk.generators.{PermissionsGen, ResourceGen} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ApiMappings -import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.User +import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.acls import ch.epfl.bluebrain.nexus.delta.sdk.syntax._ import ch.epfl.bluebrain.nexus.delta.sdk.utils.Fixtures -import ch.epfl.bluebrain.nexus.delta.sourcing.model.Label -import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef +import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.User +import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Label, ProjectRef} import ch.epfl.bluebrain.nexus.testkit.{CirceLiteral, IOValues, TestHelpers, TestMatchers} import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike @@ -54,8 +52,7 @@ class ResourceFSpec ProjectRef.unsafe("org", "proj"), jsonContentOf("resources/resource-with-context.json") ), - Set(nxv + "TestResource"), - am = ApiMappings("_" -> schemas.resources) + Set(nxv + "TestResource") ) "be converted to Json-LD compacted" in { diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceUrisSpec.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceUrisSpec.scala index bbda8f0784..dd3522d84d 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceUrisSpec.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/model/ResourceUrisSpec.scala @@ -5,10 +5,7 @@ import ch.epfl.bluebrain.nexus.delta.kernel.utils.UrlUtils import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.{nxv, schemas} import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress import ch.epfl.bluebrain.nexus.delta.sdk.model.ResourceUris.{EphemeralResourceInProjectUris, ResourceInProjectAndSchemaUris, ResourceInProjectUris} -import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectBase} -import ch.epfl.bluebrain.nexus.delta.sourcing.model.Label -import ch.epfl.bluebrain.nexus.delta.sourcing.model.ResourceRef.Latest -import ch.epfl.bluebrain.nexus.delta.sourcing.model.ProjectRef +import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Label, ProjectRef} import ch.epfl.bluebrain.nexus.testkit.TestHelpers.genString import org.scalatest.Inspectors import org.scalatest.matchers.should.Matchers @@ -17,15 +14,6 @@ import org.scalatest.wordspec.AnyWordSpecLike class ResourceUrisSpec extends AnyWordSpecLike with Matchers with Inspectors { implicit private val baseUri: BaseUri = BaseUri("http://localhost", Label.unsafe("v1")) - private val mapping = ApiMappings( - "nxv" -> nxv.base, - "resolvers" -> schemas.resolvers, - "_" -> schemas.resources, - "schema" -> schemas.shacl, - "resolver" -> schemas.resolvers, - "resource" -> schemas.resources - ) - private val base = ProjectBase.unsafe(schemas.base) "ResourceUris" should { val projectRef = ProjectRef.unsafe("myorg", "myproject") @@ -34,7 +22,6 @@ class ResourceUrisSpec extends AnyWordSpecLike with Matchers with Inspectors { "be constructed for permissions" in { val expected = Uri("http://localhost/v1/permissions") ResourceUris.permissions.accessUri shouldEqual expected - ResourceUris.permissions.accessUriShortForm shouldEqual expected } "be constructed for acls" in { @@ -48,7 +35,6 @@ class ResourceUrisSpec extends AnyWordSpecLike with Matchers with Inspectors { ) forAll(list) { case (resourceUris, expected) => resourceUris.accessUri shouldEqual expected - resourceUris.accessUriShortForm shouldEqual expected } } @@ -57,125 +43,88 @@ class ResourceUrisSpec extends AnyWordSpecLike with Matchers with Inspectors { val expected = Uri("http://localhost/v1/realms/myrealm") val resourceUris = ResourceUris.realm(myrealm) resourceUris.accessUri shouldEqual expected - resourceUris.accessUriShortForm shouldEqual expected } "be constructed for organizations" in { val expected = Uri("http://localhost/v1/orgs/myorg") val resourceUris = ResourceUris.organization(projectRef.organization) resourceUris.accessUri shouldEqual expected - resourceUris.accessUriShortForm shouldEqual expected } "be constructed for projects" in { val expected = Uri("http://localhost/v1/projects/myorg/myproject") val resourceUris = ResourceUris.project(projectRef) resourceUris.accessUri shouldEqual expected - resourceUris.accessUriShortForm shouldEqual expected } "be constructed for resources" in { - val id = nxv + "myid" - val encodedId = UrlUtils.encode(id.toString) - forAll(List(schemas.resources -> "_", schemas.resolvers -> "resolver")) { case (schema, shortForm) => - val encodedSchema = UrlUtils.encode(schema.toString) - val expected = Uri(s"http://localhost/v1/resources/myorg/myproject/$encodedSchema/$encodedId") - val expectedIn = Uri(s"http://localhost/v1/resources/myorg/myproject/$encodedSchema/$encodedId/incoming") - val expectedOut = Uri(s"http://localhost/v1/resources/myorg/myproject/$encodedSchema/$encodedId/outgoing") - val expectedShort = Uri(s"http://localhost/v1/resources/myorg/myproject/$shortForm/nxv:myid") - val expectedInShort = Uri(s"http://localhost/v1/resources/myorg/myproject/$shortForm/nxv:myid/incoming") - val expectedOutShort = Uri(s"http://localhost/v1/resources/myorg/myproject/$shortForm/nxv:myid/outgoing") - - val resourceUris = ResourceUris - .resource(projectRef, projectRefSchema, id, Latest(schema))(mapping, base) - .asInstanceOf[ResourceInProjectAndSchemaUris] + val id = nxv + "myid" + val encodedId = UrlUtils.encode(id.toString) + val expected = Uri(s"http://localhost/v1/resources/myorg/myproject/_/$encodedId") + val expectedIn = Uri(s"http://localhost/v1/resources/myorg/myproject/_/$encodedId/incoming") + val expectedOut = Uri(s"http://localhost/v1/resources/myorg/myproject/_/$encodedId/outgoing") - resourceUris.accessUri shouldEqual expected - resourceUris.accessUriShortForm shouldEqual expectedShort - resourceUris.incoming shouldEqual expectedIn - resourceUris.outgoing shouldEqual expectedOut - resourceUris.incomingShortForm shouldEqual expectedInShort - resourceUris.outgoingShortForm shouldEqual expectedOutShort - resourceUris.project shouldEqual Uri(s"http://localhost/v1/projects/myorg/myproject") - resourceUris.schemaProject shouldEqual Uri(s"http://localhost/v1/projects/myorg/myproject2") - } + val resourceUris = + ResourceUris.resource(projectRef, projectRefSchema, id).asInstanceOf[ResourceInProjectAndSchemaUris] + + resourceUris.accessUri shouldEqual expected + resourceUris.incoming shouldEqual expectedIn + resourceUris.outgoing shouldEqual expectedOut + resourceUris.project shouldEqual Uri(s"http://localhost/v1/projects/myorg/myproject") + resourceUris.schemaProject shouldEqual Uri(s"http://localhost/v1/projects/myorg/myproject2") } "be constructed for schemas" in { - val id = schemas + "myid" - val expected = Uri(s"http://localhost/v1/schemas/myorg/myproject/${UrlUtils.encode(id.toString)}") - val expectedIn = Uri(s"http://localhost/v1/schemas/myorg/myproject/${UrlUtils.encode(id.toString)}/incoming") - val expectedOut = Uri(s"http://localhost/v1/schemas/myorg/myproject/${UrlUtils.encode(id.toString)}/outgoing") - val expectedShort = Uri("http://localhost/v1/schemas/myorg/myproject/myid") - val expectedInShort = Uri("http://localhost/v1/schemas/myorg/myproject/myid/incoming") - val expectedOutShort = Uri("http://localhost/v1/schemas/myorg/myproject/myid/outgoing") + val id = schemas + "myid" + val expected = Uri(s"http://localhost/v1/schemas/myorg/myproject/${UrlUtils.encode(id.toString)}") + val expectedIn = Uri(s"http://localhost/v1/schemas/myorg/myproject/${UrlUtils.encode(id.toString)}/incoming") + val expectedOut = Uri(s"http://localhost/v1/schemas/myorg/myproject/${UrlUtils.encode(id.toString)}/outgoing") - val resourceUris = ResourceUris.schema(projectRef, id)(mapping, base).asInstanceOf[ResourceInProjectUris] + val resourceUris = ResourceUris.schema(projectRef, id).asInstanceOf[ResourceInProjectUris] resourceUris.accessUri shouldEqual expected - resourceUris.accessUriShortForm shouldEqual expectedShort - resourceUris.accessUriShortForm shouldEqual expectedShort resourceUris.incoming shouldEqual expectedIn resourceUris.outgoing shouldEqual expectedOut - resourceUris.incomingShortForm shouldEqual expectedInShort - resourceUris.outgoingShortForm shouldEqual expectedOutShort resourceUris.project shouldEqual Uri(s"http://localhost/v1/projects/myorg/myproject") } "be constructed for resolvers" in { - val id = nxv + "myid" - val expected = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}") - val expectedIn = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}/incoming") - val expectedOut = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}/outgoing") - val expectedShort = Uri("http://localhost/v1/resolvers/myorg/myproject/nxv:myid") - val expectedInShort = Uri("http://localhost/v1/resolvers/myorg/myproject/nxv:myid/incoming") - val expectedOutShort = Uri("http://localhost/v1/resolvers/myorg/myproject/nxv:myid/outgoing") - - val resourceUris = ResourceUris.resolver(projectRef, id)(mapping, base).asInstanceOf[ResourceInProjectUris] + val id = nxv + "myid" + val expected = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}") + val expectedIn = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}/incoming") + val expectedOut = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}/outgoing") + + val resourceUris = ResourceUris.resolver(projectRef, id).asInstanceOf[ResourceInProjectUris] resourceUris.accessUri shouldEqual expected - resourceUris.accessUriShortForm shouldEqual expectedShort resourceUris.incoming shouldEqual expectedIn resourceUris.outgoing shouldEqual expectedOut - resourceUris.incomingShortForm shouldEqual expectedInShort - resourceUris.outgoingShortForm shouldEqual expectedOutShort resourceUris.project shouldEqual Uri(s"http://localhost/v1/projects/myorg/myproject") } "be constructed for resolvers with nxv as a base" in { - val id = nxv + "myid" - val expected = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}") - val expectedIn = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}/incoming") - val expectedOut = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}/outgoing") - val expectedShort = Uri("http://localhost/v1/resolvers/myorg/myproject/myid") - val expectedInShort = Uri("http://localhost/v1/resolvers/myorg/myproject/myid/incoming") - val expectedOutShort = Uri("http://localhost/v1/resolvers/myorg/myproject/myid/outgoing") - - val m = ApiMappings("resolvers" -> schemas.resolvers) + val id = nxv + "myid" + val expected = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}") + val expectedIn = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}/incoming") + val expectedOut = Uri(s"http://localhost/v1/resolvers/myorg/myproject/${UrlUtils.encode(id.toString)}/outgoing") val resourceUris = - ResourceUris.resolver(projectRef, id)(m, ProjectBase.unsafe(nxv.base)).asInstanceOf[ResourceInProjectUris] + ResourceUris.resolver(projectRef, id).asInstanceOf[ResourceInProjectUris] resourceUris.accessUri shouldEqual expected - resourceUris.accessUriShortForm shouldEqual expectedShort resourceUris.incoming shouldEqual expectedIn resourceUris.outgoing shouldEqual expectedOut - resourceUris.incomingShortForm shouldEqual expectedInShort - resourceUris.outgoingShortForm shouldEqual expectedOutShort resourceUris.project shouldEqual Uri(s"http://localhost/v1/projects/myorg/myproject") - } "be constructed for ephemeral resources" in { val segment = genString() val id = nxv + "myid" val expected = Uri(s"http://localhost/v1/$segment/myorg/myproject/${UrlUtils.encode(id.toString)}") - val expectedShort = Uri(s"http://localhost/v1/$segment/myorg/myproject/nxv:myid") val expectedProject = Uri(s"http://localhost/v1/projects/myorg/myproject") - val resourceUris = ResourceUris.ephemeral(segment, projectRef, id)(mapping, base) + val resourceUris = ResourceUris.ephemeral(segment, projectRef, id) resourceUris match { case v: EphemeralResourceInProjectUris => v.accessUri shouldEqual expected - v.accessUriShortForm shouldEqual expectedShort v.project shouldEqual expectedProject case other => fail( diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImplSpec.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImplSpec.scala index 06c6f8f7af..0a9c97caf0 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImplSpec.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resolvers/ResolversImplSpec.scala @@ -121,7 +121,7 @@ class ResolversImplSpec val payload = sourceWithoutId(value) resolvers .create(id, projectRef, payload) - .accepted shouldEqual resolverResourceFor(id, project, value, payload, subject = bob.subject) + .accepted shouldEqual resolverResourceFor(id, projectRef, value, payload, subject = bob.subject) } // Dependency to the referenced project should have been saved @@ -140,7 +140,7 @@ class ResolversImplSpec val payload = sourceFrom(id, value) resolvers.create(projectRef, payload).accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, payload, subject = bob.subject @@ -163,7 +163,7 @@ class ResolversImplSpec .create(id, projectRef, payload)(alice) .accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, payload, subject = alice.subject @@ -177,7 +177,7 @@ class ResolversImplSpec val payload = sourceWithoutId(expectedValue) resolvers.create(projectRef, payload).accepted shouldEqual resolverResourceFor( expectedId, - project, + projectRef, expectedValue, payload, subject = bob.subject @@ -193,7 +193,7 @@ class ResolversImplSpec ) { case (id, value) => resolvers.create(id, projectRef, value).accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, ResolverValue.generateSource(id, value), subject = bob.subject @@ -339,7 +339,7 @@ class ResolversImplSpec .update(id, projectRef, 1, payload) .accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, payload, rev = 2, @@ -357,7 +357,7 @@ class ResolversImplSpec ) { case (id, value) => resolvers.update(id, projectRef, 1, value).accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, ResolverValue.generateSource(id, value), rev = 2, @@ -471,7 +471,7 @@ class ResolversImplSpec ) { case (id, value) => resolvers.tag(id, projectRef, tag, 1, 2).accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, sourceWithoutId(value), tags = Tags(tag -> 1), @@ -547,7 +547,7 @@ class ResolversImplSpec ) { case (id, value) => resolvers.deprecate(id, projectRef, 3).accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, sourceWithoutId(value), tags = Tags(tag -> 1), @@ -635,7 +635,7 @@ class ResolversImplSpec ) { case (id, value) => resolvers.tag(id, projectRef, tag2, 4, 4).accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, sourceWithoutId(value), tags = Tags(tag -> 1, tag2 -> 4), @@ -649,7 +649,7 @@ class ResolversImplSpec val inProjectExpected = resolverResourceFor( nxv + "in-project", - project, + projectRef, updatedInProjectValue, sourceWithoutId(updatedInProjectValue), tags = Tags(tag -> 1, tag2 -> 4), @@ -659,7 +659,7 @@ class ResolversImplSpec ) val crossProjectExpected = resolverResourceFor( nxv + "cross-project", - project, + projectRef, updatedCrossProjectValue, sourceWithoutId(updatedCrossProjectValue), tags = Tags(tag -> 1, tag2 -> 4), @@ -679,7 +679,7 @@ class ResolversImplSpec "succeed by rev" in { val inProjectExpectedByRev = resolverResourceFor( nxv + "in-project", - project, + projectRef, updatedInProjectValue, sourceWithoutId(updatedInProjectValue), tags = Tags(tag -> 1), @@ -688,7 +688,7 @@ class ResolversImplSpec ) val crossProjectExpectedByRev = resolverResourceFor( nxv + "cross-project", - project, + projectRef, updatedCrossProjectValue, sourceWithoutId(updatedCrossProjectValue), tags = Tags(tag -> 1), @@ -711,7 +711,7 @@ class ResolversImplSpec ) { case (id, value) => resolvers.fetch(IdSegmentRef(id, tag), projectRef).accepted shouldEqual resolverResourceFor( id, - project, + projectRef, value, sourceWithoutId(value), subject = bob.subject @@ -770,14 +770,14 @@ class ResolversImplSpec results.results.map(_.source) should contain theSameElementsAs Vector( resolverResourceFor( nxv + "in-project-both", - project, + projectRef, inProj, sourceFrom(nxv + "in-project-both", inProj), subject = alice.subject ), resolverResourceFor( nxv + "cross-project-both", - project, + projectRef, crossProj, sourceFrom(nxv + "cross-project-both", crossProj), subject = alice.subject diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesImplSpec.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesImplSpec.scala index 05e1ec6692..14871e744a 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesImplSpec.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesImplSpec.scala @@ -129,9 +129,7 @@ class ResourcesImplSpec resource shouldEqual ResourceGen.resourceFor( expectedData, types = types, - subject = subject, - am = allApiMappings, - base = projBase + subject = subject ) } } @@ -151,9 +149,7 @@ class ResourcesImplSpec resource shouldEqual ResourceGen.resourceFor( expectedData, types = types, - subject = subject, - am = allApiMappings, - base = projBase + subject = subject ) } } @@ -174,9 +170,7 @@ class ResourcesImplSpec resource shouldEqual ResourceGen.resourceFor( expectedData, types = types, - subject = subject, - am = allApiMappings, - base = projBase + subject = subject ) } } @@ -190,7 +184,7 @@ class ResourcesImplSpec ResourceGen.resource(myId7, projectRef, payloadWithCtx, schemaRev).copy(source = payload) resources.create(myId7, projectRef, schemas.resources, payload).accepted shouldEqual - ResourceGen.resourceFor(expectedData, subject = subject, am = allApiMappings, base = projBase) + ResourceGen.resourceFor(expectedData, subject = subject) } "succeed with the id present on the payload and pointing to another resource in its context" in { @@ -203,9 +197,7 @@ class ResourcesImplSpec resource shouldEqual ResourceGen.resourceFor( expectedData, types = types, - subject = subject, - am = allApiMappings, - base = projBase + subject = subject ) } @@ -218,9 +210,7 @@ class ResourcesImplSpec resource shouldEqual ResourceGen.resourceFor( expectedData, types = types, - subject = subject, - am = allApiMappings, - base = projBase + subject = subject ) } @@ -309,9 +299,7 @@ class ResourcesImplSpec expectedData, types = types, subject = subject, - rev = 2, - am = allApiMappings, - base = projBase + rev = 2 ) } @@ -323,9 +311,7 @@ class ResourcesImplSpec expectedData, types = types, subject = subject, - rev = 3, - am = allApiMappings, - base = projBase + rev = 3 ) } @@ -382,9 +368,7 @@ class ResourcesImplSpec expectedData, types = types, subject = subject, - rev = 2, - am = allApiMappings, - base = projBase + rev = 2 ) } @@ -396,9 +380,7 @@ class ResourcesImplSpec expectedData, types = types, subject = subject, - rev = 3, - am = allApiMappings, - base = projBase + rev = 3 ) } @@ -447,9 +429,7 @@ class ResourcesImplSpec expectedData, types = types, subject = subject, - rev = 2, - am = allApiMappings, - base = projBase + rev = 2 ) } @@ -519,9 +499,7 @@ class ResourcesImplSpec types = types, subject = subject, rev = 2, - deprecated = true, - am = allApiMappings, - base = projBase + deprecated = true ) } @@ -567,9 +545,7 @@ class ResourcesImplSpec expectedDataLatest, types = types, subject = subject, - rev = 2, - am = allApiMappings, - base = projBase + rev = 2 ) } } @@ -580,9 +556,7 @@ class ResourcesImplSpec ResourceGen.resourceFor( expectedData, types = types, - subject = subject, - am = allApiMappings, - base = projBase + subject = subject ) } } @@ -593,9 +567,7 @@ class ResourcesImplSpec ResourceGen.resourceFor( expectedData, types = types, - subject = subject, - am = allApiMappings, - base = projBase + subject = subject ) } } @@ -649,9 +621,7 @@ class ResourcesImplSpec expectedData, types = types, subject = subject, - rev = 3, - am = allApiMappings, - base = projBase + rev = 3 ) } diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/SchemasImplSpec.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/SchemasImplSpec.scala index 525442fbe9..efe363aae0 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/SchemasImplSpec.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/SchemasImplSpec.scala @@ -100,21 +100,21 @@ class SchemasImplSpec "succeed with the id present on the payload" in { schemas.create(projectRef, source).accepted shouldEqual - SchemaGen.resourceFor(schema, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schema, subject = subject) } "succeed with the id present on the payload and passed" in { val source = schemaSourceWithId(mySchema2) val schema = SchemaGen.schema(mySchema2, project.ref, source) schemas.create("myschema2", projectRef, source).accepted shouldEqual - SchemaGen.resourceFor(schema, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schema, subject = subject) } "succeed with the passed id" in { val source = schemaSourceWithId(mySchema3) val schema = SchemaGen.schema(mySchema3, project.ref, source).copy(source = sourceNoId) schemas.create(mySchema3, projectRef, sourceNoId).accepted shouldEqual - SchemaGen.resourceFor(schema, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schema, subject = subject) } "reject with different ids on the payload and passed" in { @@ -148,7 +148,7 @@ class SchemasImplSpec "succeed" in { schemas.update(mySchema, projectRef, 1, sourceUpdated).accepted shouldEqual - SchemaGen.resourceFor(schemaUpdated, rev = 2, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schemaUpdated, rev = 2, subject = subject) } "reject if it doesn't exists" in { @@ -186,12 +186,12 @@ class SchemasImplSpec "create the schema for subsequent tests" in { schemas.create(projectRef, schemaSourceWithId(mySchema4)).accepted shouldEqual - SchemaGen.resourceFor(schema4, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schema4, subject = subject) } "succeed" in { schemas.refresh(mySchema4, projectRef).accepted shouldEqual - SchemaGen.resourceFor(schema4, rev = 2, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schema4, rev = 2, subject = subject) } "reject if it doesn't exists" in { @@ -219,7 +219,7 @@ class SchemasImplSpec val schema = SchemaGen.schema(mySchema2, project.ref, schemaSourceWithId(mySchema2), tags = Tags(tag -> 1)) schemas.tag(mySchema2, projectRef, tag, 1, 1).accepted shouldEqual - SchemaGen.resourceFor(schema, subject = subject, rev = 2, am = am, base = projBase) + SchemaGen.resourceFor(schema, subject = subject, rev = 2) } "reject if it doesn't exists" in { @@ -240,8 +240,6 @@ class SchemasImplSpec schema, subject = subject, rev = 3, - am = am, - base = projBase, deprecated = true ) } @@ -266,7 +264,7 @@ class SchemasImplSpec "succeed" in { schemas.deprecate(mySchema, projectRef, 2).accepted shouldEqual - SchemaGen.resourceFor(schemaUpdated, subject = subject, rev = 3, deprecated = true, am = am, base = projBase) + SchemaGen.resourceFor(schemaUpdated, subject = subject, rev = 3, deprecated = true) } "reject if it doesn't exists" in { @@ -298,17 +296,17 @@ class SchemasImplSpec "succeed" in { schemas.fetch(mySchema, projectRef).accepted shouldEqual - SchemaGen.resourceFor(schemaUpdated, rev = 3, deprecated = true, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schemaUpdated, rev = 3, deprecated = true, subject = subject) } "succeed by tag" in { schemas.fetch(IdSegmentRef(mySchema2, tag), projectRef).accepted shouldEqual - SchemaGen.resourceFor(schema2, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schema2, subject = subject) } "succeed by rev" in { schemas.fetch(IdSegmentRef(mySchema2, 1), projectRef).accepted shouldEqual - SchemaGen.resourceFor(schema2, subject = subject, am = am, base = projBase) + SchemaGen.resourceFor(schema2, subject = subject) } "reject if tag does not exist" in { @@ -340,7 +338,7 @@ class SchemasImplSpec val sourceWithId = schemaSourceWithId(mySchema2) val schema = SchemaGen.schema(mySchema2, project.ref, sourceWithId) schemas.deleteTag(mySchema2, projectRef, tag, 2).accepted shouldEqual - SchemaGen.resourceFor(schema, subject = subject, rev = 3, am = am, base = projBase) + SchemaGen.resourceFor(schema, subject = subject, rev = 3) } "reject if the schema doesn't exist" in { schemas.deleteTag(nxv + "other", projectRef, tag, 1).rejectedWith[SchemaNotFound] diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/utils/RouteFixtures.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/utils/RouteFixtures.scala index 0886b398ce..6590dac9d2 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/utils/RouteFixtures.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/utils/RouteFixtures.scala @@ -2,7 +2,6 @@ package ch.epfl.bluebrain.nexus.delta.sdk.utils import akka.http.scaladsl.model.Uri import akka.http.scaladsl.server.{ExceptionHandler, RejectionHandler} -import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.contexts import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.{JsonLdApi, JsonLdJavaApi} import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, RemoteContextResolution} @@ -65,7 +64,4 @@ trait RouteFixtures extends TestHelpers with IOValues { val realm: Label = Label.unsafe("wonderland") val alice: User = User("alice", realm) val bob: User = User("bob", realm) - - def lastSegment(iri: Iri): String = - iri.toString.substring(iri.toString.lastIndexOf("/") + 1) } diff --git a/docs/src/main/paradox/docs/releases/index.md b/docs/src/main/paradox/docs/releases/index.md index 11fcf42b50..ed1ad237a6 100644 --- a/docs/src/main/paradox/docs/releases/index.md +++ b/docs/src/main/paradox/docs/releases/index.md @@ -1,6 +1,7 @@ @@@ index - @ref:[v1.9 Release Notes](v1.9-release-notes.md) +- @ref:[v1.8 To v1.9 Migration](v1.8-to-v1.9-migration.md) - @ref:[v1.8 Release Notes](v1.8-release-notes.md) - @ref:[v1.7 To v1.8 Migration](v1.7-to-v1.8-migration.md) - @ref:[v1.7 Release Notes](v1.7-release-notes.md) diff --git a/docs/src/main/paradox/docs/releases/v1.8-to-v1.9-migration.md b/docs/src/main/paradox/docs/releases/v1.8-to-v1.9-migration.md new file mode 100644 index 0000000000..3b7c036703 --- /dev/null +++ b/docs/src/main/paradox/docs/releases/v1.8-to-v1.9-migration.md @@ -0,0 +1,25 @@ +# v1.8 To v1.9 Migration + +## self, incoming and outgoing links + +@@@ note { .warning title="Reindexing" } + +Reindexing can consume a lot of CPU/memory if many views are indexing in parallel, please proceed by restarting only a subset of them at a time so as to not +overload the system. + +@@@ + +As those links are not shortened anymore (@ref:[see here](./v1.9-release-notes.md#self-incoming-and-outgoing-links)), +we encourage Nexus deployments moving to 1.9 to reindex your different views containing metadata. + +This operation can be performing by deleting the offset for the different views by using the different endpoints: + +* @ref:[Elasticsearch views](../delta/api/views/elasticsearch-view-api.md#restart-indexing) +* @ref:[Blazegraph views](../delta/api/views/sparql-view-api.md#restart-indexing) +* @ref:[Composite views](../delta/api/views/composite-view-api.md#restart-indexing) + +Nexus Fusion also allows to restart the indexing for the different views. + +## Composite views + +TODO \ No newline at end of file diff --git a/docs/src/main/paradox/docs/releases/v1.9-release-notes.md b/docs/src/main/paradox/docs/releases/v1.9-release-notes.md index 286abf3328..71cf7048f8 100644 --- a/docs/src/main/paradox/docs/releases/v1.9-release-notes.md +++ b/docs/src/main/paradox/docs/releases/v1.9-release-notes.md @@ -8,6 +8,21 @@ TODO add potential migration page ### Resources +#### self, incoming and outgoing links + +Those three links are returned in the response of operations related to the different resources. +Until 1.9, they were curied/shortened according to the base and the API mappings defined in the project configuration. + +This caused consistency problems as whenever the base or the API mapping were changing, those shortened links were +not valid anymore: + +* All data in views displaying metadata (which include those links) had to be indexed again ; +* The change had also to be propagated to other external systems ; +* The resources including download links to files had to be patched + +Therefore since 1.9, `_self`, `_incoming` and `outgoing` links are not shortened anymore allowing them to remain stable in +time even if the project configuration changes. + #### Multi fetch Multiple resources can now be retrieved within a single call with the multi-fetch operation. diff --git a/tests/src/test/resources/kg/archives/archive-response.json b/tests/src/test/resources/kg/archives/archive-response.json index c57402946c..787a2fdbab 100644 --- a/tests/src/test/resources/kg/archives/archive-response.json +++ b/tests/src/test/resources/kg/archives/archive-response.json @@ -22,7 +22,7 @@ "rev": 1 } ], - "_self": "{{deltaUri}}/archives/{{project1}}/test-resource:archive", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/archives.json", "_project": "{{deltaUri}}/projects/{{project1}}", "_rev": 1, diff --git a/tests/src/test/resources/kg/files/attachment-metadata.json b/tests/src/test/resources/kg/files/attachment-metadata.json index a3f786ca58..ffc94418f7 100644 --- a/tests/src/test/resources/kg/files/attachment-metadata.json +++ b/tests/src/test/resources/kg/files/attachment-metadata.json @@ -18,9 +18,9 @@ "_filename": "{{filename}}", "_mediaType": "application/json", "_origin" : "Client", - "_incoming": "{{deltaUri}}/files/{{projId}}/{{filename}}/incoming", - "_outgoing": "{{deltaUri}}/files/{{projId}}/{{filename}}/outgoing", - "_self": "{{deltaUri}}/files/{{projId}}/{{filename}}", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/files.json", "_project": "{{project}}", "_rev": 3, diff --git a/tests/src/test/resources/kg/files/attachment2-metadata.json b/tests/src/test/resources/kg/files/attachment2-metadata.json index 075f03023d..383b92cd84 100644 --- a/tests/src/test/resources/kg/files/attachment2-metadata.json +++ b/tests/src/test/resources/kg/files/attachment2-metadata.json @@ -3,7 +3,7 @@ "https://bluebrain.github.io/nexus/contexts/files.json", "https://bluebrain.github.io/nexus/contexts/metadata.json" ], - "@id": "{{deltaUri}}/resources/{{projId}}/_/attachment2", + "@id": "{{id}}", "@type": "File", "_storage": { "@id": "https://bluebrain.github.io/nexus/vocabulary/{{storageId}}", @@ -18,9 +18,9 @@ "_filename": "attachment2", "_mediaType": "text/plain; charset=UTF-8", "_origin" : "Client", - "_incoming": "{{deltaUri}}/files/{{projId}}/attachment2/incoming", - "_outgoing": "{{deltaUri}}/files/{{projId}}/attachment2/outgoing", - "_self": "{{deltaUri}}/files/{{projId}}/attachment2", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/files.json", "_project": "{{project}}", "_rev": 1, diff --git a/tests/src/test/resources/kg/files/linking-metadata.json b/tests/src/test/resources/kg/files/linking-metadata.json index 646ed0d0b1..f038b39370 100644 --- a/tests/src/test/resources/kg/files/linking-metadata.json +++ b/tests/src/test/resources/kg/files/linking-metadata.json @@ -19,9 +19,9 @@ "_location": "{{endpointBucket}}/{{key}}", "_mediaType": "image/png", "_origin" : "Storage", - "_incoming": "{{deltaUri}}/files/{{projId}}/logo.png/incoming", - "_outgoing": "{{deltaUri}}/files/{{projId}}/logo.png/outgoing", - "_self": "{{deltaUri}}/files/{{projId}}/logo.png", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/files.json", "_project": "{{deltaUri}}/projects/{{projId}}", "_rev": 1, diff --git a/tests/src/test/resources/kg/files/list.json b/tests/src/test/resources/kg/files/list.json index f3fb01dcce..38f634a71c 100644 --- a/tests/src/test/resources/kg/files/list.json +++ b/tests/src/test/resources/kg/files/list.json @@ -17,12 +17,12 @@ "_value": "0e5ce4e33df07eb312e462d9b4646aebf44e7c4d758891e632dbb0533df85e3f" }, "_filename": "attachment.json", - "_incoming": "{{deltaUri}}/files/{{project}}/attachment.json/incoming", + "_incoming": "{{fileSelfPrefix}}attachment.json/incoming", "_mediaType": "application/json", - "_outgoing": "{{deltaUri}}/files/{{project}}/attachment.json/outgoing", + "_outgoing": "{{fileSelfPrefix}}attachment.json/outgoing", "_project": "{{deltaUri}}/projects/{{project}}", "_rev": 3, - "_self": "{{deltaUri}}/files/{{project}}/attachment.json", + "_self": "{{fileSelfPrefix}}attachment.json", "_storage": { "@id": "https://bluebrain.github.io/nexus/vocabulary/{{storageId}}", "@type": "{{storageType}}", @@ -42,12 +42,12 @@ "_value": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" }, "_filename": "empty", - "_incoming": "{{deltaUri}}/files/{{project}}/empty/incoming", + "_incoming": "{{fileSelfPrefix}}empty/incoming", "_mediaType": "text/plain; charset=UTF-8", - "_outgoing": "{{deltaUri}}/files/{{project}}/empty/outgoing", + "_outgoing": "{{fileSelfPrefix}}empty/outgoing", "_project": "{{deltaUri}}/projects/{{project}}", "_rev": 1, - "_self": "{{deltaUri}}/files/{{project}}/empty", + "_self": "{{fileSelfPrefix}}empty", "_storage": { "@id": "https://bluebrain.github.io/nexus/vocabulary/{{storageId}}", "@type": "{{storageType}}", @@ -67,12 +67,12 @@ "_value": "62ad07ee5e775552034186daafd7d77054620f2bc9fb8da629fd7af24b4c84e7" }, "_filename": "attachment2", - "_incoming": "{{deltaUri}}/files/{{project}}/attachment2/incoming", + "_incoming": "{{fileSelfPrefix}}attachment2/incoming", "_mediaType": "text/plain; charset=UTF-8", - "_outgoing": "{{deltaUri}}/files/{{project}}/attachment2/outgoing", + "_outgoing": "{{fileSelfPrefix}}attachment2/outgoing", "_project": "{{deltaUri}}/projects/{{project}}", "_rev": 1, - "_self": "{{deltaUri}}/files/{{project}}/attachment2", + "_self": "{{fileSelfPrefix}}attachment2", "_storage": { "@id": "https://bluebrain.github.io/nexus/vocabulary/{{storageId}}", "@type": "{{storageType}}", @@ -92,12 +92,12 @@ "_value": "62ad07ee5e775552034186daafd7d77054620f2bc9fb8da629fd7af24b4c84e7" }, "_filename": "attachment2", - "_incoming": "{{deltaUri}}/files/{{project}}/attachment3/incoming", + "_incoming": "{{fileSelfPrefix}}attachment3/incoming", "_mediaType": "text/plain; charset=UTF-8", - "_outgoing": "{{deltaUri}}/files/{{project}}/attachment3/outgoing", + "_outgoing": "{{fileSelfPrefix}}attachment3/outgoing", "_project": "{{deltaUri}}/projects/{{project}}", "_rev": 1, - "_self": "{{deltaUri}}/files/{{project}}/attachment3", + "_self": "{{fileSelfPrefix}}attachment3", "_storage": { "@id": "https://bluebrain.github.io/nexus/vocabulary/{{storageId}}2", "@type": "{{storageType}}", diff --git a/tests/src/test/resources/kg/files/remote-linked.json b/tests/src/test/resources/kg/files/remote-linked.json index 4de425d17e..0ea6dd24fa 100644 --- a/tests/src/test/resources/kg/files/remote-linked.json +++ b/tests/src/test/resources/kg/files/remote-linked.json @@ -13,13 +13,13 @@ "_value": "" }, "_filename": "{{filename}}", - "_incoming": "{{deltaUri}}/files/{{projId}}/{{filename}}/incoming", "_mediaType": "text/plain", "_origin": "Storage", - "_outgoing": "{{deltaUri}}/files/{{projId}}/{{filename}}/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "{{project}}", "_rev": 1, - "_self": "{{deltaUri}}/files/{{projId}}/{{filename}}", + "_self": "{{self}}", "_storage": { "@id": "https://bluebrain.github.io/nexus/vocabulary/{{storageId}}", "@type": "{{storageType}}", diff --git a/tests/src/test/resources/kg/files/remote-updated-linked.json b/tests/src/test/resources/kg/files/remote-updated-linked.json index b925c03959..ad0aadccd5 100644 --- a/tests/src/test/resources/kg/files/remote-updated-linked.json +++ b/tests/src/test/resources/kg/files/remote-updated-linked.json @@ -14,13 +14,13 @@ "_value": "694b27f021c4861b3373cd5ddbc42695c056d0a4297d2d85e2dae040a84e61df" }, "_filename": "{{filename}}", - "_incoming": "{{deltaUri}}/files/{{projId}}/{{filename}}/incoming", + "_incoming": "{{self}}/incoming", "_mediaType": "text/plain", "_origin": "Storage", - "_outgoing": "{{deltaUri}}/files/{{projId}}/{{filename}}/outgoing", + "_outgoing": "{{self}}/outgoing", "_project": "{{project}}", "_rev": 2, - "_self": "{{deltaUri}}/files/{{projId}}/{{filename}}", + "_self": "{{self}}", "_storage": { "@id": "https://bluebrain.github.io/nexus/vocabulary/{{storageId}}", "@type": "{{storageType}}", diff --git a/tests/src/test/resources/kg/files/sparql.json b/tests/src/test/resources/kg/files/sparql.json index 57f817bfe8..c9ae92c7f8 100644 --- a/tests/src/test/resources/kg/files/sparql.json +++ b/tests/src/test/resources/kg/files/sparql.json @@ -169,7 +169,7 @@ { "object": { "type": "uri", - "value": "{{deltaUri}}/files/{{project}}/attachment.json" + "value": "{{self}}" }, "predicate": { "type": "uri", @@ -183,7 +183,7 @@ { "object": { "type": "uri", - "value": "{{deltaUri}}/files/{{project}}/attachment.json/incoming" + "value": "{{self}}/incoming" }, "predicate": { "type": "uri", @@ -197,7 +197,7 @@ { "object": { "type": "uri", - "value": "{{deltaUri}}/files/{{project}}/attachment.json/outgoing" + "value": "{{self}}/outgoing" }, "predicate": { "type": "uri", diff --git a/tests/src/test/resources/kg/listings/all/resource-by-type-1.json b/tests/src/test/resources/kg/listings/all/resource-by-type-1.json index 380b660a12..65e3a6b425 100644 --- a/tests/src/test/resources/kg/listings/all/resource-by-type-1.json +++ b/tests/src/test/resources/kg/listings/all/resource-by-type-1.json @@ -12,12 +12,9 @@ "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/unconstrained.json", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", "_deprecated": true, - "_incoming": "{{deltaUri}}/resources/{{org}}/{{proj}}/_/resource12/incoming", - "_outgoing": "{{deltaUri}}/resources/{{org}}/{{proj}}/_/resource12/outgoing", "_project": "{{deltaUri}}/projects/{{org}}/{{proj}}", "_rev": 2, "_schemaProject": "{{deltaUri}}/projects/{{org}}/{{proj}}", - "_self": "{{deltaUri}}/resources/{{org}}/{{proj}}/_/resource12", "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" } ] diff --git a/tests/src/test/resources/kg/listings/all/resource-by-type-4.json b/tests/src/test/resources/kg/listings/all/resource-by-type-4.json index d39c04cf28..ce161b996a 100644 --- a/tests/src/test/resources/kg/listings/all/resource-by-type-4.json +++ b/tests/src/test/resources/kg/listings/all/resource-by-type-4.json @@ -12,12 +12,9 @@ "_constrainedBy": "https://dev.nexus.test.com/test-schema", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", "_deprecated": false, - "_incoming": "{{deltaUri}}/resources/{{org1}}/{{proj1}}/test-schema/resource11_with_schema/incoming", - "_outgoing": "{{deltaUri}}/resources/{{org1}}/{{proj1}}/test-schema/resource11_with_schema/outgoing", "_project": "{{deltaUri}}/projects/{{org1}}/{{proj1}}", "_rev": 1, "_schemaProject": "{{deltaUri}}/projects/{{org1}}/{{proj1}}", - "_self": "{{deltaUri}}/resources/{{org1}}/{{proj1}}/test-schema/resource11_with_schema", "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" }, { @@ -26,12 +23,9 @@ "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/unconstrained.json", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", "_deprecated": false, - "_incoming": "{{deltaUri}}/resources/{{org2}}/{{proj3}}/_/resource21/incoming", - "_outgoing": "{{deltaUri}}/resources/{{org2}}/{{proj3}}/_/resource21/outgoing", "_project": "{{deltaUri}}/projects/{{org2}}/{{proj3}}", "_rev": 2, "_schemaProject": "{{deltaUri}}/projects/{{org2}}/{{proj3}}", - "_self": "{{deltaUri}}/resources/{{org2}}/{{proj3}}/_/resource21", "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" }, { @@ -40,12 +34,9 @@ "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/unconstrained.json", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", "_deprecated": true, - "_incoming": "{{deltaUri}}/resources/{{org1}}/{{proj2}}/_/resource12/incoming", - "_outgoing": "{{deltaUri}}/resources/{{org1}}/{{proj2}}/_/resource12/outgoing", "_project": "{{deltaUri}}/projects/{{org1}}/{{proj2}}", "_rev": 2, "_schemaProject": "{{deltaUri}}/projects/{{org1}}/{{proj2}}", - "_self": "{{deltaUri}}/resources/{{org1}}/{{proj2}}/_/resource12", "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" }, { @@ -54,12 +45,9 @@ "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/unconstrained.json", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", "_deprecated": false, - "_incoming": "{{deltaUri}}/resources/{{org1}}/{{proj1}}/_/resource11/incoming", - "_outgoing": "{{deltaUri}}/resources/{{org1}}/{{proj1}}/_/resource11/outgoing", "_project": "{{deltaUri}}/projects/{{org1}}/{{proj1}}", "_rev": 2, "_schemaProject": "{{deltaUri}}/projects/{{org1}}/{{proj1}}", - "_self": "{{deltaUri}}/resources/{{org1}}/{{proj1}}/_/resource11", "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" } ] diff --git a/tests/src/test/resources/kg/listings/default-resolver.json b/tests/src/test/resources/kg/listings/default-resolver.json index f72411eb3f..675d47da67 100644 --- a/tests/src/test/resources/kg/listings/default-resolver.json +++ b/tests/src/test/resources/kg/listings/default-resolver.json @@ -7,14 +7,14 @@ "_total": 1, "_results": [ { - "@id": "https://bluebrain.github.io/nexus/vocabulary/defaultInProject", + "@id": "{{id}}", "@type": [ "Resolver", "InProject" ], - "_incoming": "{{deltaUri}}/resolvers/{{project-label}}/defaultResolver/incoming", - "_outgoing": "{{deltaUri}}/resolvers/{{project-label}}/defaultResolver/outgoing", - "_self": "{{deltaUri}}/resolvers/{{project-label}}/defaultResolver", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/resolvers.json", "_project": "{{project}}", "name" : "Default resolver", diff --git a/tests/src/test/resources/kg/listings/default-storage.json b/tests/src/test/resources/kg/listings/default-storage.json index 56cbfd6170..34550e1751 100644 --- a/tests/src/test/resources/kg/listings/default-storage.json +++ b/tests/src/test/resources/kg/listings/default-storage.json @@ -7,15 +7,15 @@ "_total": 1, "_results": [ { - "@id": "https://bluebrain.github.io/nexus/vocabulary/diskStorageDefault", + "@id": "{{id}}", "@type": [ "Storage", "DiskStorage" ], "_algorithm": "SHA-256", - "_incoming": "{{deltaUri}}/storages/{{project-label}}/defaultStorage/incoming", - "_outgoing": "{{deltaUri}}/storages/{{project-label}}/defaultStorage/outgoing", - "_self": "{{deltaUri}}/storages/{{project-label}}/defaultStorage", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/storages.json", "_project": "{{project}}", "_rev": 1, diff --git a/tests/src/test/resources/kg/listings/default-view.json b/tests/src/test/resources/kg/listings/default-view.json index 6aecae8957..b5482ce768 100644 --- a/tests/src/test/resources/kg/listings/default-view.json +++ b/tests/src/test/resources/kg/listings/default-view.json @@ -7,14 +7,14 @@ "_total": 3, "_results": [ { - "@id": "https://bluebrain.github.io/nexus/vocabulary/defaultElasticSearchIndex", + "@id": "{{defaultElasticSearchView}}", "@type": [ "ElasticSearchView", "View" ], - "_incoming": "{{deltaUri}}/views/{{project-label}}/documents/incoming", - "_outgoing": "{{deltaUri}}/views/{{project-label}}/documents/outgoing", - "_self": "{{deltaUri}}/views/{{project-label}}/documents", + "_incoming": "{{defaultElasticSearchViewSelf}}/incoming", + "_outgoing": "{{defaultElasticSearchViewSelf}}/outgoing", + "_self": "{{defaultElasticSearchViewSelf}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/views.json", "_project": "{{project}}", "_rev": 1, @@ -25,14 +25,14 @@ "name" : "Default Elasticsearch view" }, { - "@id": "https://bluebrain.github.io/nexus/vocabulary/defaultSparqlIndex", + "@id": "{{defaultSparqlView}}", "@type": [ "View", "SparqlView" ], - "_incoming": "{{deltaUri}}/views/{{project-label}}/graph/incoming", - "_outgoing": "{{deltaUri}}/views/{{project-label}}/graph/outgoing", - "_self": "{{deltaUri}}/views/{{project-label}}/graph", + "_incoming": "{{defaultSparqlViewSelf}}/incoming", + "_outgoing": "{{defaultSparqlViewSelf}}/outgoing", + "_self": "{{defaultSparqlViewSelf}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/views.json", "_project": "{{project}}", "_rev": 1, @@ -43,7 +43,7 @@ "name" : "Default Sparql view" }, { - "@id": "https://bluebrain.github.io/nexus/vocabulary/searchView", + "@id": "{{searchView}}", "@type": [ "View", "CompositeView" @@ -51,11 +51,11 @@ "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/views.json", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", "_deprecated": false, - "_incoming": "{{deltaUri}}/views/{{project-label}}/nxv:searchView/incoming", - "_outgoing": "{{deltaUri}}/views/{{project-label}}/nxv:searchView/outgoing", + "_incoming": "{{searchViewSelf}}/incoming", + "_outgoing": "{{searchViewSelf}}/outgoing", + "_self": "{{searchViewSelf}}", "_project": "{{project}}", "_rev": 1, - "_self": "{{deltaUri}}/views/{{project-label}}/nxv:searchView", "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" } ] diff --git a/tests/src/test/resources/kg/listings/project/resource-by-type.json b/tests/src/test/resources/kg/listings/project/resource-by-type.json deleted file mode 100644 index 8ce8115aac..0000000000 --- a/tests/src/test/resources/kg/listings/project/resource-by-type.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "@context": [ - "https://bluebrain.github.io/nexus/contexts/metadata.json", - "https://bluebrain.github.io/nexus/contexts/search.json", - "https://bluebrain.github.io/nexus/contexts/search-metadata.json" - ], - "_total": 2, - "_results": [ - { - "@id": "{{deltaUri}}/resources/{{proj}}/_/resource11", - "@type": "{{resourceType}}", - "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/unconstrained.json", - "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", - "_deprecated": false, - "_incoming": "{{deltaUri}}/resources/{{org}}/{{proj}}/_/resource11/incoming", - "_outgoing": "{{deltaUri}}/resources/{{org}}/{{proj}}/_/resource11/outgoing", - "_project": "{{deltaUri}}/projects/{{org}}/{{proj}}", - "_rev": 2, - "_schemaProject": "{{deltaUri}}/projects/{{org}}/{{proj}}", - "_self": "{{deltaUri}}/resources/{{org}}/{{proj}}/_/resource11", - "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" - }, - { - "@id": "{{deltaUri}}/resources/{{proj}}/_/resource11_with_schema", - "@type": "{{resourceType}}", - "_constrainedBy": "https://dev.nexus.test.com/test-schema", - "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", - "_deprecated": false, - "_incoming": "{{deltaUri}}/resources/{{org}}/{{proj}}/test-schema/resource11_with_schema/incoming", - "_outgoing": "{{deltaUri}}/resources/{{org}}/{{proj}}/test-schema/resource11_with_schema/outgoing", - "_project": "{{deltaUri}}/projects/{{org}}/{{proj}}", - "_rev": 1, - "_schemaProject": "{{deltaUri}}/projects/{{org}}/{{proj}}", - "_self": "{{deltaUri}}/resources/{{org}}/{{proj}}/test-schema/resource11_with_schema", - "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" - } - ] -} \ No newline at end of file diff --git a/tests/src/test/resources/kg/listings/project/resource11-schema.json b/tests/src/test/resources/kg/listings/project/resource11-schema.json index c03b23c7e8..96940b1093 100644 --- a/tests/src/test/resources/kg/listings/project/resource11-schema.json +++ b/tests/src/test/resources/kg/listings/project/resource11-schema.json @@ -7,17 +7,17 @@ "_total": 1, "_results": [ { - "@id": "{{deltaUri}}/resources/{{proj}}/_/resource11_with_schema", + "@id": "{{id}}", "@type": "{{resourceType}}", "_constrainedBy": "https://dev.nexus.test.com/test-schema", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", "_deprecated": false, - "_incoming": "{{deltaUri}}/resources/{{org}}/{{proj}}/test-schema/resource11_with_schema/incoming", - "_outgoing": "{{deltaUri}}/resources/{{org}}/{{proj}}/test-schema/resource11_with_schema/outgoing", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", "_project": "{{deltaUri}}/projects/{{org}}/{{proj}}", "_rev": 1, "_schemaProject": "{{deltaUri}}/projects/{{org}}/{{proj}}", - "_self": "{{deltaUri}}/resources/{{org}}/{{proj}}/test-schema/resource11_with_schema", + "_self": "{{self}}", "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" } ] diff --git a/tests/src/test/resources/kg/resources/cross-project-resolver-list.json b/tests/src/test/resources/kg/resources/cross-project-resolver-list.json deleted file mode 100644 index 77f38d2114..0000000000 --- a/tests/src/test/resources/kg/resources/cross-project-resolver-list.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "@context": [ - "https://bluebrain.github.io/nexus/contexts/metadata.json", - "https://bluebrain.github.io/nexus/contexts/search.json", - "https://bluebrain.github.io/nexus/contexts/search-metadata.json" - ], - "_total": 2, - "_results": [ - { - "@id": "https://bluebrain.github.io/nexus/vocabulary/defaultInProject", - "@type": [ - "Resolver", - "InProject" - ], - "_incoming": "{{deltaUri}}/resolvers/{{projId}}/defaultResolver/incoming", - "_outgoing": "{{deltaUri}}/resolvers/{{projId}}/defaultResolver/outgoing", - "_self": "{{deltaUri}}/resolvers/{{projId}}/defaultResolver", - "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/resolvers.json", - "_project": "{{project}}", - "_rev": 1, - "_deprecated": false, - "_createdBy": "{{deltaUri}}/realms/internal/users/service-account-delta", - "_updatedBy": "{{deltaUri}}/realms/internal/users/service-account-delta", - "name" : "Default resolver" - }, - { - "@id": "http://localhost/resolver", - "@type": [ - "Resolver", - "CrossProject" - ], - "_incoming": "{{deltaUri}}/resolvers/{{projId}}/test-resolver/incoming", - "_outgoing": "{{deltaUri}}/resolvers/{{projId}}/test-resolver/outgoing", - "_self": "{{deltaUri}}/resolvers/{{projId}}/test-resolver", - "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/resolvers.json", - "_project": "{{project}}", - "_rev": 2, - "_deprecated": false, - "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", - "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}" - } - ] -} \ No newline at end of file diff --git a/tests/src/test/resources/kg/resources/cross-project-resolver-updated-resp.json b/tests/src/test/resources/kg/resources/cross-project-resolver-updated-resp.json index 6fd060015c..7e0648b935 100644 --- a/tests/src/test/resources/kg/resources/cross-project-resolver-updated-resp.json +++ b/tests/src/test/resources/kg/resources/cross-project-resolver-updated-resp.json @@ -26,9 +26,9 @@ } ], "priority": 20, - "_incoming": "{{resources}}/test-resolver/incoming", - "_outgoing": "{{resources}}/test-resolver/outgoing", - "_self": "{{resources}}/test-resolver", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/resolvers.json", "_project": "{{project-parent}}", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", diff --git a/tests/src/test/resources/kg/resources/simple-resource-response.json b/tests/src/test/resources/kg/resources/simple-resource-response.json index 4ead6420ee..28b59847c0 100644 --- a/tests/src/test/resources/kg/resources/simple-resource-response.json +++ b/tests/src/test/resources/kg/resources/simple-resource-response.json @@ -13,9 +13,9 @@ "testProject" ], "other:priority": {{priority}}, - "_incoming": "{{resources}}/test-schema/test-resource:{{resourceId}}/incoming", - "_outgoing": "{{resources}}/test-schema/test-resource:{{resourceId}}/outgoing", - "_self" : "{{resources}}/test-schema/test-resource:{{resourceId}}", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self" : "{{self}}", "_project" : "{{project}}", "_schemaProject" : "{{project}}", "_constrainedBy": "https://dev.nexus.test.com/test-schema", diff --git a/tests/src/test/resources/kg/resources/simple-resource-with-metadata.json b/tests/src/test/resources/kg/resources/simple-resource-with-metadata.json index 06a24055a9..bb7ebdee01 100644 --- a/tests/src/test/resources/kg/resources/simple-resource-with-metadata.json +++ b/tests/src/test/resources/kg/resources/simple-resource-with-metadata.json @@ -5,9 +5,9 @@ "_constrainedBy": "https://dev.nexus.test.com/test-schema", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", "_updatedBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", - "_incoming": "{{resources}}/test-schema/test-resource:{{resourceId}}/incoming", - "_outgoing": "{{resources}}/test-schema/test-resource:{{resourceId}}/outgoing", - "_self": "{{resources}}/test-schema/test-resource:{{resourceId}}", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_project": "{{project}}", "_schemaProject": "{{project}}", "_rev": {{rev}}, diff --git a/tests/src/test/resources/kg/storages/disk-response.json b/tests/src/test/resources/kg/storages/disk-response.json index b508d7f3d9..e5b0689d76 100644 --- a/tests/src/test/resources/kg/storages/disk-response.json +++ b/tests/src/test/resources/kg/storages/disk-response.json @@ -14,9 +14,9 @@ "readPermission": "{{read}}", "writePermission": "{{write}}", "_algorithm": "SHA-256", - "_incoming": "{{deltaUri}}/storages/{{project}}/nxv:{{id}}/incoming", - "_outgoing": "{{deltaUri}}/storages/{{project}}/nxv:{{id}}/outgoing", - "_self": "{{deltaUri}}/storages/{{project}}/nxv:{{id}}", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/storages.json", "_project": "{{deltaUri}}/projects/{{project}}", "_rev": 1, diff --git a/tests/src/test/resources/kg/storages/s3-response.json b/tests/src/test/resources/kg/storages/s3-response.json index e6c9838614..39c10537ea 100644 --- a/tests/src/test/resources/kg/storages/s3-response.json +++ b/tests/src/test/resources/kg/storages/s3-response.json @@ -15,9 +15,9 @@ "readPermission": "{{read}}", "writePermission": "{{write}}", "_algorithm": "SHA-256", - "_incoming": "{{deltaUri}}/storages/{{project}}/nxv:{{id}}/incoming", - "_outgoing": "{{deltaUri}}/storages/{{project}}/nxv:{{id}}/outgoing", - "_self": "{{deltaUri}}/storages/{{project}}/nxv:{{id}}", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/storages.json", "_project": "{{deltaUri}}/projects/{{project}}", "_rev": 1, diff --git a/tests/src/test/resources/kg/views/elasticsearch/aggregate-response.json b/tests/src/test/resources/kg/views/elasticsearch/aggregate-response.json index 56ecb5304c..54da43f1a0 100644 --- a/tests/src/test/resources/kg/views/elasticsearch/aggregate-response.json +++ b/tests/src/test/resources/kg/views/elasticsearch/aggregate-response.json @@ -18,9 +18,9 @@ "viewId": "https://dev.nexus.test.com/simplified-resource/cell-view" } ], - "_incoming": "{{resources}}/incoming", - "_outgoing": "{{resources}}/outgoing", - "_self": "{{resources}}", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/views.json", "_project": "{{project-parent}}", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", diff --git a/tests/src/test/resources/kg/views/sparql-view-response.json b/tests/src/test/resources/kg/views/sparql-view-response.json index 5e5e4fc6fb..b75f0075a4 100644 --- a/tests/src/test/resources/kg/views/sparql-view-response.json +++ b/tests/src/test/resources/kg/views/sparql-view-response.json @@ -21,9 +21,9 @@ "includeDeprecated": false, "includeMetadata": false, "permission": "views/query", - "_incoming": "{{resources}}/incoming", - "_outgoing": "{{resources}}/outgoing", - "_self": "{{resources}}", + "_incoming": "{{self}}/incoming", + "_outgoing": "{{self}}/outgoing", + "_self": "{{self}}", "_constrainedBy": "https://bluebrain.github.io/nexus/schemas/views.json", "_project": "{{project-parent}}", "_createdBy": "{{deltaUri}}/realms/{{realm}}/users/{{user}}", diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/BaseSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/BaseSpec.scala index 3d04e51553..cb459f091b 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/BaseSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/BaseSpec.scala @@ -236,6 +236,26 @@ trait BaseSpec private[tests] def expectOk[A] = expect(StatusCodes.OK) private[tests] def tag(name: String, rev: Int) = json"""{"tag": "$name", "rev": $rev}""" + + private[tests] def resourceSelf(project: String, id: String): String = { + val uri = Uri(s"${config.deltaUri}/resources/$project/_") + uri.copy(path = uri.path / id).toString + } + + private[tests] def resolverSelf(project: String, id: String): String = { + val uri = Uri(s"${config.deltaUri}/resolvers/$project") + uri.copy(path = uri.path / id).toString + } + + private[tests] def viewSelf(project: String, id: String): String = { + val uri = Uri(s"${config.deltaUri}/views/$project") + uri.copy(path = uri.path / id).toString + } + + private[tests] def storageSelf(project: String, id: String): String = { + val uri = Uri(s"${config.deltaUri}/storages/$project") + uri.copy(path = uri.path / id).toString + } } object BaseSpec { diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/Optics.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/Optics.scala index 08c3a86a42..ce8b9f84c5 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/Optics.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/Optics.scala @@ -52,6 +52,10 @@ object Optics extends Optics { val filterSearchMetadata: Json => Json = filterKey("_next") andThen filterResultMetadata + private val linkKeys = Set("_self", "_incoming", "_outgoing") + val filterResultMetadataAndLinks: Json => Json = filterResults(metadataKeys ++ linkKeys) + val filterSearchMetadataAndLinks: Json => Json = filterKey("_next") andThen filterResultMetadataAndLinks + val `@id` = root.`@id`.string val _uuid = root._uuid.string diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ArchiveSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ArchiveSpec.scala index e19d6c6fd4..6c5b5df548 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ArchiveSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ArchiveSpec.scala @@ -1,7 +1,7 @@ package ch.epfl.bluebrain.nexus.tests.kg import akka.http.scaladsl.model.headers.{Accept, Location} -import akka.http.scaladsl.model.{MediaRanges, MediaTypes, StatusCodes} +import akka.http.scaladsl.model.{MediaRanges, MediaTypes, StatusCodes, Uri} import akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers import akka.util.ByteString import ch.epfl.bluebrain.nexus.delta.kernel.utils.UrlUtils @@ -46,7 +46,7 @@ class ArchiveSpec extends BaseSpec with ArchiveHelpers with CirceEq { "user" -> Tweety.name, "priority" -> "5", "rev" -> "1", - "resources" -> s"${config.deltaUri}/resources/$fullId", + "self" -> resourceSelf(fullId, "https://dev.nexus.test.com/simplified-resource/1"), "project" -> s"${config.deltaUri}/projects/$fullId", "resourceId" -> "1" ) @@ -58,7 +58,7 @@ class ArchiveSpec extends BaseSpec with ArchiveHelpers with CirceEq { "user" -> Tweety.name, "priority" -> "6", "rev" -> "1", - "resources" -> s"${config.deltaUri}/resources/$fullId2", + "self" -> resourceSelf(fullId2, "https://dev.nexus.test.com/simplified-resource/2"), "project" -> s"${config.deltaUri}/projects/$fullId2", "resourceId" -> "2" ) @@ -66,6 +66,11 @@ class ArchiveSpec extends BaseSpec with ArchiveHelpers with CirceEq { private val nexusLogoDigest = "edd70eff895cde1e36eaedd22ed8e9c870bb04155d05d275f970f4f255488e993a32a7c914ee195f6893d43b8be4e0b00db0a6d545a8462491eae788f664ea6b" + private[tests] def archiveSelf(project: String, id: String): String = { + val uri = Uri(s"${config.deltaUri}/archives/$project") + uri.copy(path = uri.path / id).toString + } + "Setup" should { "create projects, resources and add necessary acls" in { @@ -216,6 +221,7 @@ class ArchiveSpec extends BaseSpec with ArchiveHelpers with CirceEq { replacements( Tweety, "project2" -> fullId2, + "self" -> archiveSelf(fullId, "https://dev.nexus.test.com/simplified-resource/archive"), "project1" -> fullId ): _* ) diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/DiskStorageSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/DiskStorageSpec.scala index b482e01eef..da77ec16ba 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/DiskStorageSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/DiskStorageSpec.scala @@ -18,51 +18,46 @@ class DiskStorageSpec extends StorageSpec { override def locationPrefix: Option[String] = None + private def storageResponse(project: String, id: String, readPermission: String, writePermission: String) = + jsonContentOf( + "/kg/storages/disk-response.json", + replacements( + Coyote, + "id" -> id, + "project" -> project, + "self" -> storageSelf(project, s"https://bluebrain.github.io/nexus/vocabulary/$id"), + "read" -> readPermission, + "maxFileSize" -> storageConfig.maxFileSize.toString, + "write" -> writePermission + ): _* + ) + override def createStorages: Task[Assertion] = { val payload = jsonContentOf("/kg/storages/disk.json") val payload2 = jsonContentOf("/kg/storages/disk-perms.json") for { - _ <- deltaClient.post[Json](s"/storages/$fullId", payload, Coyote) { (_, response) => - response.status shouldEqual StatusCodes.Created - } - _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId", Coyote) { (json, response) => - val expected = jsonContentOf( - "/kg/storages/disk-response.json", - replacements( - Coyote, - "id" -> storageId, - "project" -> fullId, - "read" -> "resources/read", - "maxFileSize" -> storageConfig.maxFileSize.toString, - "write" -> "files/write" - ): _* - ) - filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) - response.status shouldEqual StatusCodes.OK - } - _ <- permissionDsl.addPermissions( - Permission(storageName, "read"), - Permission(storageName, "write") - ) - _ <- deltaClient.post[Json](s"/storages/$fullId", payload2, Coyote) { (_, response) => - response.status shouldEqual StatusCodes.Created - } - _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:${storageId}2", Coyote) { (json, response) => - val expected = jsonContentOf( - "/kg/storages/disk-response.json", - replacements( - Coyote, - "id" -> s"${storageId}2", - "project" -> fullId, - "read" -> s"$storageName/read", - "maxFileSize" -> storageConfig.maxFileSize.toString, - "write" -> s"$storageName/write" - ): _* - ) - filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) - response.status shouldEqual StatusCodes.OK - } + _ <- deltaClient.post[Json](s"/storages/$fullId", payload, Coyote) { (_, response) => + response.status shouldEqual StatusCodes.Created + } + _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId", Coyote) { (json, response) => + val expected = storageResponse(fullId, storageId, "resources/read", "files/write") + filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) + response.status shouldEqual StatusCodes.OK + } + _ <- permissionDsl.addPermissions( + Permission(storageName, "read"), + Permission(storageName, "write") + ) + _ <- deltaClient.post[Json](s"/storages/$fullId", payload2, Coyote) { (_, response) => + response.status shouldEqual StatusCodes.Created + } + storageId2 = s"${storageId}2" + _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId2", Coyote) { (json, response) => + val expected = storageResponse(fullId, storageId2, s"$storageName/read", s"$storageName/write") + filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) + response.status shouldEqual StatusCodes.OK + } } yield succeed } diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ElasticSearchViewsSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ElasticSearchViewsSpec.scala index 9fc243ffd7..5e53ae7a0b 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ElasticSearchViewsSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ElasticSearchViewsSpec.scala @@ -96,6 +96,7 @@ class ElasticSearchViewsSpec extends BaseSpec with EitherValuable with CirceEq { } "get the created elasticsearch views" in { + val id = "https://dev.nexus.test.com/simplified-resource/cell-view" projects.parTraverse { project => deltaClient.get[Json](s"/views/$project/test-resource:cell-view", ScoobyDoo) { (json, response) => response.status shouldEqual StatusCodes.OK @@ -103,8 +104,8 @@ class ElasticSearchViewsSpec extends BaseSpec with EitherValuable with CirceEq { "/kg/views/elasticsearch/indexing-response.json", replacements( ScoobyDoo, - "id" -> "https://dev.nexus.test.com/simplified-resource/cell-view", - "self" -> s"${config.deltaUri}/views/$project/test-resource:cell-view", + "id" -> id, + "self" -> viewSelf(project, id), "project-parent" -> s"${config.deltaUri}/projects/$project", "project" -> project ): _* @@ -126,6 +127,7 @@ class ElasticSearchViewsSpec extends BaseSpec with EitherValuable with CirceEq { } "get the created AggregateElasticSearchView" in { + val id = "https://dev.nexus.test.com/simplified-resource/agg-cell-view" deltaClient.get[Json](s"/views/$fullId2/test-resource:agg-cell-view", ScoobyDoo) { (json, response) => response.status shouldEqual StatusCodes.OK @@ -133,8 +135,8 @@ class ElasticSearchViewsSpec extends BaseSpec with EitherValuable with CirceEq { "/kg/views/elasticsearch/aggregate-response.json", replacements( ScoobyDoo, - "id" -> "https://dev.nexus.test.com/simplified-resource/agg-cell-view", - "resources" -> s"${config.deltaUri}/views/$fullId2/test-resource:agg-cell-view", + "id" -> id, + "self" -> viewSelf(fullId2, id), "project-parent" -> s"${config.deltaUri}/projects/$fullId2", "project1" -> fullId, "project2" -> fullId2 diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ListingsSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ListingsSpec.scala index b2b05b2407..91642a716c 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ListingsSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ListingsSpec.scala @@ -6,7 +6,7 @@ import ch.epfl.bluebrain.nexus.testkit.{CirceEq, EitherValuable} import ch.epfl.bluebrain.nexus.tests.{BaseSpec, SchemaPayload} import ch.epfl.bluebrain.nexus.tests.Identity.listings.{Alice, Bob} import ch.epfl.bluebrain.nexus.tests.Identity.{Anonymous, Delta} -import ch.epfl.bluebrain.nexus.tests.Optics.{filterMetadataKeys, filterSearchMetadata, listing} +import ch.epfl.bluebrain.nexus.tests.Optics._ import ch.epfl.bluebrain.nexus.tests.iam.types.Permission.{Organizations, Resources, Views} import io.circe.Json import org.scalatest.Inspectors @@ -74,36 +74,86 @@ final class ListingsSpec extends BaseSpec with Inspectors with EitherValuable wi "Listing resources within a project" should { - "get default resources" in { + "get default resolver" in { + val defaultResolverId = "https://bluebrain.github.io/nexus/vocabulary/defaultInProject" + val mapping = replacements( Delta, "project-label" -> ref11, - "project" -> s"${config.deltaUri}/projects/$ref11" + "project" -> s"${config.deltaUri}/projects/$ref11", + "id" -> defaultResolverId, + "self" -> resolverSelf(ref11, defaultResolverId) ) - val endpoints = List( - s"/resolvers/$ref11" -> jsonContentOf("/kg/listings/default-resolver.json", mapping: _*), - s"/views/$ref11" -> jsonContentOf("/kg/listings/default-view.json", mapping: _*), - s"/storages/$ref11" -> jsonContentOf("/kg/listings/default-storage.json", mapping: _*) + val expected = jsonContentOf("/kg/listings/default-resolver.json", mapping: _*) + + eventually { + deltaClient.get[Json](s"/resolvers/$ref11", Bob) { (json, response) => + response.status shouldEqual StatusCodes.OK + filterSearchMetadata(json) should equalIgnoreArrayOrder(expected) + } + } + } + + "get default views" in { + val defaultElasticSearchView = "https://bluebrain.github.io/nexus/vocabulary/defaultElasticSearchIndex" + val defaultSparqlView = "https://bluebrain.github.io/nexus/vocabulary/defaultSparqlIndex" + val searchView = "https://bluebrain.github.io/nexus/vocabulary/searchView" + + val mapping = replacements( + Delta, + "project-label" -> ref11, + "project" -> s"${config.deltaUri}/projects/$ref11", + "defaultElasticSearchView" -> defaultElasticSearchView, + "defaultElasticSearchViewSelf" -> viewSelf(ref11, defaultElasticSearchView), + "defaultSparqlView" -> defaultSparqlView, + "defaultSparqlViewSelf" -> viewSelf(ref11, defaultSparqlView), + "searchView" -> searchView, + "searchViewSelf" -> viewSelf(ref11, searchView) ) - forAll(endpoints) { case (endpoint, expected) => - eventually { - deltaClient.get[Json](endpoint, Bob) { (json, response) => - response.status shouldEqual StatusCodes.OK - filterSearchMetadata(json) should equalIgnoreArrayOrder(expected) - } + val expected = jsonContentOf("/kg/listings/default-view.json", mapping: _*) + eventually { + deltaClient.get[Json](s"/views/$ref11", Bob) { (json, response) => + response.status shouldEqual StatusCodes.OK + filterSearchMetadata(json) should equalIgnoreArrayOrder(expected) } } } + "get default storage" in { + val defaultStorageId = "https://bluebrain.github.io/nexus/vocabulary/diskStorageDefault" + + val mapping = replacements( + Delta, + "project-label" -> ref11, + "project" -> s"${config.deltaUri}/projects/$ref11", + "id" -> defaultStorageId, + "self" -> storageSelf(ref11, defaultStorageId) + ) + + val expected = jsonContentOf("/kg/listings/default-storage.json", mapping: _*) + + eventually { + deltaClient.get[Json](s"/storages/$ref11", Bob) { (json, response) => + response.status shouldEqual StatusCodes.OK + filterSearchMetadata(json) should equalIgnoreArrayOrder(expected) + } + } + } + + val resource11Id = s"${config.deltaUri}/resources/$proj11/_/resource11" + val resource11WithSchemaId = s"${config.deltaUri}/resources/$proj11/_/resource11_with_schema" + val resource11WithSchemaSelf = resourceSelf(ref11, resource11WithSchemaId) val resource11WithSchemaResult = jsonContentOf( "/kg/listings/project/resource11-schema.json", replacements( Bob, "org" -> org1, "proj" -> proj11, - "resourceType" -> resourceType + "resourceType" -> resourceType, + "id" -> resource11WithSchemaId, + "self" -> resource11WithSchemaSelf ): _* ) @@ -115,22 +165,22 @@ final class ListingsSpec extends BaseSpec with Inspectors with EitherValuable wi } "get the resource via locate with an id and id parameters" in { - val id = UrlUtils.encode(s"${config.deltaUri}/resources/$proj11/_/resource11_with_schema") - deltaClient.get[Json](s"/resources?id=$id", Bob) { (json, response) => + val encodedId = UrlUtils.encode(resource11WithSchemaId) + deltaClient.get[Json](s"/resources?id=$encodedId", Bob) { (json, response) => response.status shouldEqual StatusCodes.OK filterSearchMetadata(json) should equalIgnoreArrayOrder(resource11WithSchemaResult) } - deltaClient.get[Json](s"/resources?locate=$id", Bob) { (json, response) => + deltaClient.get[Json](s"/resources?locate=$encodedId", Bob) { (json, response) => response.status shouldEqual StatusCodes.OK filterSearchMetadata(json) should equalIgnoreArrayOrder(resource11WithSchemaResult) } } "get the resource via locate with a self " in { - val self = UrlUtils.encode(s"${config.deltaUri}/resources/$ref11/test-schema/resource11_with_schema") + val encodedSelf = UrlUtils.encode(resource11WithSchemaSelf) - deltaClient.get[Json](s"/resources?locate=$self", Bob) { (json, response) => + deltaClient.get[Json](s"/resources?locate=$encodedSelf", Bob) { (json, response) => response.status shouldEqual StatusCodes.OK filterSearchMetadata(json) should equalIgnoreArrayOrder(resource11WithSchemaResult) } @@ -154,7 +204,7 @@ final class ListingsSpec extends BaseSpec with Inspectors with EitherValuable wi def lens(json: Json) = listing._results .getOption(json) - .fold(Vector.empty[Json]) { _.map(filterMetadataKeys) } + .fold(Vector.empty[String]) { _.flatMap(`@id`.getOption) } val result = deltaClient .stream( @@ -166,19 +216,7 @@ final class ListingsSpec extends BaseSpec with Inspectors with EitherValuable wi .compile .toList - val expected = listing._results - .getOption( - jsonContentOf( - "/kg/listings/project/resource-by-type.json", - replacements( - Bob, - "org" -> org1, - "proj" -> proj11, - "resourceType" -> resourceType - ): _* - ) - ) - .value + val expected = Vector(resource11Id, resource11WithSchemaId) result.map(_.flatten shouldEqual expected) } @@ -251,7 +289,7 @@ final class ListingsSpec extends BaseSpec with Inspectors with EitherValuable wi eventually { deltaClient.get[Json](s"/resources?type=$testResourceType", Bob) { (json, response) => response.status shouldEqual StatusCodes.OK - filterSearchMetadata(json) should equalIgnoreArrayOrder(expected) + filterSearchMetadataAndLinks(json) should equalIgnoreArrayOrder(expected) } } } @@ -269,7 +307,7 @@ final class ListingsSpec extends BaseSpec with Inspectors with EitherValuable wi deltaClient.get[Json](s"/resources?type=$testResourceType", Alice) { (json, response) => response.status shouldEqual StatusCodes.OK - filterSearchMetadata(json) should equalIgnoreArrayOrder(expected) + filterSearchMetadataAndLinks(json) should equalIgnoreArrayOrder(expected) } } diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/RemoteStorageSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/RemoteStorageSpec.scala index 65e7f629af..02f0e44143 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/RemoteStorageSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/RemoteStorageSpec.scala @@ -16,6 +16,7 @@ import org.scalatest.{Assertion, Ignore} import scala.annotation.nowarn import scala.sys.process._ +// Ignore while https://github.com/BlueBrain/nexus/issues/4063 is ongoing @Ignore class RemoteStorageSpec extends StorageSpec { @@ -44,6 +45,22 @@ class RemoteStorageSpec extends StorageSpec { () } + private def storageResponse(project: String, id: String, readPermission: String, writePermission: String) = + jsonContentOf( + "/kg/storages/remote-disk-response.json", + replacements( + Coyote, + "endpoint" -> externalEndpoint, + "folder" -> remoteFolder, + "id" -> id, + "project" -> project, + "self" -> storageSelf(project, s"https://bluebrain.github.io/nexus/vocabulary/$id"), + "maxFileSize" -> storageConfig.maxFileSize.toString, + "read" -> readPermission, + "write" -> writePermission + ): _* + ) + override def createStorages: Task[Assertion] = { val payload = jsonContentOf( "/kg/storages/remote-disk.json", @@ -64,62 +81,39 @@ class RemoteStorageSpec extends StorageSpec { ) for { - _ <- deltaClient.post[Json](s"/storages/$fullId", payload, Coyote) { (json, response) => - if (response.status != StatusCodes.Created) { - fail(s"Unexpected status '${response.status}', response:\n${json.spaces2}") - } else succeed - } - _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId", Coyote) { (json, response) => - val expected = jsonContentOf( - "/kg/storages/remote-disk-response.json", - replacements( - Coyote, - "endpoint" -> externalEndpoint, - "folder" -> remoteFolder, - "id" -> storageId, - "project" -> fullId, - "maxFileSize" -> storageConfig.maxFileSize.toString, - "read" -> "resources/read", - "write" -> "files/write" - ): _* - ) - filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) - response.status shouldEqual StatusCodes.OK - } - _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId/source", Coyote) { (json, response) => - response.status shouldEqual StatusCodes.OK - val expected = jsonContentOf( - "/kg/storages/storage-source.json", - "folder" -> remoteFolder, - "storageBase" -> externalEndpoint - ) - filterKey("credentials")(json) should equalIgnoreArrayOrder(expected) - - } - _ <- permissionDsl.addPermissions( - Permission(storageName, "read"), - Permission(storageName, "write") - ) - _ <- deltaClient.post[Json](s"/storages/$fullId", payload2, Coyote) { (_, response) => - response.status shouldEqual StatusCodes.Created - } - _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:${storageId}2", Coyote) { (json, response) => - val expected = jsonContentOf( - "/kg/storages/remote-disk-response.json", - replacements( - Coyote, - "endpoint" -> externalEndpoint, - "folder" -> remoteFolder, - "id" -> s"${storageId}2", - "project" -> fullId, - "maxFileSize" -> storageConfig.maxFileSize.toString, - "read" -> s"$storageName/read", - "write" -> s"$storageName/write" - ): _* - ) - filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) - response.status shouldEqual StatusCodes.OK - } + _ <- deltaClient.post[Json](s"/storages/$fullId", payload, Coyote) { (json, response) => + if (response.status != StatusCodes.Created) { + fail(s"Unexpected status '${response.status}', response:\n${json.spaces2}") + } else succeed + } + _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId", Coyote) { (json, response) => + val expected = storageResponse(fullId, storageId, "resources/read", "files/write") + filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) + response.status shouldEqual StatusCodes.OK + } + _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId/source", Coyote) { (json, response) => + response.status shouldEqual StatusCodes.OK + val expected = jsonContentOf( + "/kg/storages/storage-source.json", + "folder" -> remoteFolder, + "storageBase" -> externalEndpoint + ) + filterKey("credentials")(json) should equalIgnoreArrayOrder(expected) + + } + _ <- permissionDsl.addPermissions( + Permission(storageName, "read"), + Permission(storageName, "write") + ) + _ <- deltaClient.post[Json](s"/storages/$fullId", payload2, Coyote) { (_, response) => + response.status shouldEqual StatusCodes.Created + } + storageId2 = s"${storageId}2" + _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId2", Coyote) { (json, response) => + val expected = storageResponse(fullId, storageId2, s"$storageName/read", s"$storageName/write") + filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) + response.status shouldEqual StatusCodes.OK + } } yield succeed } @@ -201,17 +195,18 @@ class RemoteStorageSpec extends StorageSpec { val createFile = s"echo 'file content' > /tmp/$remoteFolder/file.txt" s"docker exec nexus-storage-service bash -c \"$createFile\"".! - val payload = Json.obj( + val payload = Json.obj( "filename" -> Json.fromString("file.txt"), "path" -> Json.fromString(s"file.txt"), "mediaType" -> Json.fromString("text/plain") ) - + val fileId = s"${config.deltaUri}/resources/$fullId/_/file.txt" val expected = jsonContentOf( "/kg/files/remote-linked.json", replacements( Coyote, - "id" -> s"${config.deltaUri}/resources/$fullId/_/file.txt", + "id" -> fileId, + "self" -> fileSelf(fullId, fileId), "filename" -> "file.txt", "storageId" -> s"${storageId}2", "storageType" -> storageType, @@ -227,11 +222,13 @@ class RemoteStorageSpec extends StorageSpec { } "fetch eventually a linked file with updated attributes" in eventually { + val fileId = s"${config.deltaUri}/resources/$fullId/_/file.txt" val expected = jsonContentOf( "/kg/files/remote-updated-linked.json", replacements( Coyote, "id" -> s"${config.deltaUri}/resources/$fullId/_/file.txt", + "self" -> fileSelf(fullId, fileId), "filename" -> "file.txt", "storageId" -> s"${storageId}2", "storageType" -> storageType, diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ResourcesSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ResourcesSpec.scala index 64b177c5d8..0e4cdccbfd 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ResourcesSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/ResourcesSpec.scala @@ -8,7 +8,8 @@ import cats.implicits._ import ch.epfl.bluebrain.nexus.delta.kernel.utils.UrlUtils import ch.epfl.bluebrain.nexus.testkit.{CirceEq, EitherValuable} import ch.epfl.bluebrain.nexus.tests.Identity.resources.{Morty, Rick} -import ch.epfl.bluebrain.nexus.tests.Optics.{filterKey, filterMetadataKeys, filterSearchMetadata} +import ch.epfl.bluebrain.nexus.tests.Optics.listing._total +import ch.epfl.bluebrain.nexus.tests.Optics.{filterKey, filterMetadataKeys} import ch.epfl.bluebrain.nexus.tests.iam.types.Permission.Organizations import ch.epfl.bluebrain.nexus.tests.{BaseSpec, Optics, SchemaPayload} import io.circe.Json @@ -34,6 +35,34 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { private val IdLens: Optional[Json, String] = root.`@id`.string private val TypeLens: Optional[Json, String] = root.`@type`.string + private val resource1Self = resourceSelf(id1, "https://dev.nexus.test.com/simplified-resource/1") + + private def resource1Response(rev: Int, priority: Int) = + jsonContentOf( + "/kg/resources/simple-resource-response.json", + replacements( + Rick, + "priority" -> priority.toString, + "rev" -> rev.toString, + "self" -> resource1Self, + "project" -> s"${config.deltaUri}/projects/$id1", + "resourceId" -> "1" + ): _* + ) + + private def resource1AnnotatedSource(rev: Int, priority: Int) = + jsonContentOf( + "/kg/resources/simple-resource-with-metadata.json", + replacements( + Rick, + "priority" -> priority.toString, + "rev" -> rev.toString, + "self" -> resource1Self, + "project" -> s"${config.deltaUri}/projects/$id1", + "resourceId" -> "1" + ): _* + ) + private def `@id`(expectedId: String) = HavePropertyMatcher[Json, String] { json => val actualId = IdLens.getOption(json) HavePropertyMatchResult( @@ -141,17 +170,7 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { "fetch the payload wih metadata" in { deltaClient.get[Json](s"/resources/$id1/test-schema/test-resource:1", Rick) { (json, response) => - val expected = jsonContentOf( - "/kg/resources/simple-resource-response.json", - replacements( - Rick, - "priority" -> "5", - "rev" -> "1", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1" - ): _* - ) + val expected = resource1Response(1, 5) response.status shouldEqual StatusCodes.OK filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) } @@ -173,18 +192,8 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { "fetch the original payload with metadata" in { deltaClient.get[Json](s"/resources/$id1/test-schema/test-resource:1/source?annotate=true", Rick) { (json, response) => - val expected = jsonContentOf( - "/kg/resources/simple-resource-with-metadata.json", - replacements( - Rick, - "rev" -> "1", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1", - "priority" -> "5" - ): _* - ) response.status shouldEqual StatusCodes.OK + val expected = resource1AnnotatedSource(1, 5) filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) } } @@ -209,11 +218,10 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { } "fetch the original payload with generated id with metadata" in { - val payload = - jsonContentOf( - "/kg/resources/simple-resource-with-id.json", - "priority" -> "5" - ) + val payload = jsonContentOf( + "/kg/resources/simple-resource-with-id.json", + "priority" -> "5" + ) var generatedId: String = "" @@ -304,7 +312,7 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { replacements( Rick, "project" -> id1, - "resources" -> s"${config.deltaUri}/resolvers/$id2", + "self" -> resolverSelf(id2, "http://localhost/resolver"), "project-parent" -> s"${config.deltaUri}/projects/$id2" ): _* ) @@ -316,20 +324,10 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { } "wait for the cross-project resolver to be indexed" in { - val expected = jsonContentOf( - "/kg/resources/cross-project-resolver-list.json", - replacements( - Rick, - "project_resolver" -> id1, - "projId" -> s"$id2", - "project" -> s"${config.deltaUri}/projects/$id2" - ): _* - ) - eventually { deltaClient.get[Json](s"/resolvers/$id2", Rick) { (json, response) => response.status shouldEqual StatusCodes.OK - filterSearchMetadata(json) should equalIgnoreArrayOrder(expected) + _total.getOption(json).value shouldEqual 2L } } } @@ -397,17 +395,8 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { } "fetch the update" in { - val expected = jsonContentOf( - "/kg/resources/simple-resource-response.json", - replacements( - Rick, - "priority" -> "3", - "rev" -> "2", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1" - ): _* - ) + val expected = resource1Response(2, 3) + List( s"/resources/$id1/test-schema/test-resource:1", s"/resources/$id1/_/test-resource:1" @@ -420,17 +409,7 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { } "fetch previous revision" in { - val expected = jsonContentOf( - "/kg/resources/simple-resource-response.json", - replacements( - Rick, - "priority" -> "5", - "rev" -> "1", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1" - ): _* - ) + val expected = resource1Response(1, 5) List( s"/resources/$id1/test-schema/test-resource:1?rev=1", @@ -446,17 +425,7 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { "fetch previous revision original payload with metadata" in { deltaClient.get[Json](s"/resources/$id1/test-schema/test-resource:1/source?rev=1&annotate=true", Rick) { (json, response) => - val expected = jsonContentOf( - "/kg/resources/simple-resource-with-metadata.json", - replacements( - Rick, - "rev" -> "1", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1", - "priority" -> "5" - ): _* - ) + val expected = resource1AnnotatedSource(1, 5) response.status shouldEqual StatusCodes.OK filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) } @@ -492,40 +461,9 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { } "fetch a tagged value" in { - val expectedTag1 = jsonContentOf( - "/kg/resources/simple-resource-response.json", - replacements( - Rick, - "priority" -> "3", - "rev" -> "2", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1" - ): _* - ) - - val expectedTag2 = jsonContentOf( - "/kg/resources/simple-resource-response.json", - replacements( - Rick, - "priority" -> "5", - "rev" -> "1", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1" - ): _* - ) - val expectedTag3 = jsonContentOf( - "/kg/resources/simple-resource-response.json", - replacements( - Rick, - "priority" -> "3", - "rev" -> "5", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1" - ): _* - ) deepMerge Json.obj("_deprecated" -> Json.fromBoolean(true)) + val expectedTag1 = resource1Response(2, 3) + val expectedTag2 = resource1Response(1, 5) + val expectedTag3 = resource1Response(5, 3) deepMerge Json.obj("_deprecated" -> Json.True) for { _ <- @@ -547,17 +485,7 @@ class ResourcesSpec extends BaseSpec with EitherValuable with CirceEq { "fetch tagged original payload with metadata" in { deltaClient.get[Json](s"/resources/$id1/test-schema/test-resource:1/source?tag=v1.0.1&annotate=true", Rick) { (json, response) => - val expected = jsonContentOf( - "/kg/resources/simple-resource-with-metadata.json", - replacements( - Rick, - "rev" -> "2", - "resources" -> s"${config.deltaUri}/resources/$id1", - "project" -> s"${config.deltaUri}/projects/$id1", - "resourceId" -> "1", - "priority" -> "3" - ): _* - ) + val expected = resource1AnnotatedSource(2, 3) response.status shouldEqual StatusCodes.OK filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) } diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/S3StorageSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/S3StorageSpec.scala index a02615e0d7..479a873e36 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/S3StorageSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/S3StorageSpec.scala @@ -66,6 +66,22 @@ class S3StorageSpec extends StorageSpec { super.afterAll() } + private def storageResponse(project: String, id: String, readPermission: String, writePermission: String) = + jsonContentOf( + "/kg/storages/s3-response.json", + replacements( + Coyote, + "id" -> id, + "project" -> project, + "self" -> storageSelf(project, s"https://bluebrain.github.io/nexus/vocabulary/$id"), + "bucket" -> bucket, + "maxFileSize" -> storageConfig.maxFileSize.toString, + "endpoint" -> s3Endpoint, + "read" -> readPermission, + "write" -> writePermission + ): _* + ) + override def createStorages: Task[Assertion] = { val payload = jsonContentOf( "/kg/storages/s3.json", @@ -86,47 +102,25 @@ class S3StorageSpec extends StorageSpec { ) for { - _ <- deltaClient.post[Json](s"/storages/$fullId", payload, Coyote) { (_, response) => - response.status shouldEqual StatusCodes.Created - } - _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId", Coyote) { (json, response) => - val expected = jsonContentOf( - "/kg/storages/s3-response.json", - replacements( - Coyote, - "id" -> storageId, - "project" -> fullId, - "bucket" -> bucket, - "maxFileSize" -> storageConfig.maxFileSize.toString, - "endpoint" -> s3Endpoint, - "read" -> "resources/read", - "write" -> "files/write" - ): _* - ) - filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) - response.status shouldEqual StatusCodes.OK - } - _ <- permissionDsl.addPermissions(Permission(storageName, "read"), Permission(storageName, "write")) - _ <- deltaClient.post[Json](s"/storages/$fullId", payload2, Coyote) { (_, response) => - response.status shouldEqual StatusCodes.Created - } - _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:${storageId}2", Coyote) { (json, response) => - val expected = jsonContentOf( - "/kg/storages/s3-response.json", - replacements( - Coyote, - "id" -> s"${storageId}2", - "project" -> fullId, - "bucket" -> bucket, - "maxFileSize" -> storageConfig.maxFileSize.toString, - "endpoint" -> s3Endpoint, - "read" -> "s3/read", - "write" -> "s3/write" - ): _* - ).deepMerge(Json.obj("region" -> Json.fromString("eu-west-2"))) - filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) - response.status shouldEqual StatusCodes.OK - } + _ <- deltaClient.post[Json](s"/storages/$fullId", payload, Coyote) { (_, response) => + response.status shouldEqual StatusCodes.Created + } + _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId", Coyote) { (json, response) => + val expected = storageResponse(fullId, storageId, "resources/read", "files/write") + filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) + response.status shouldEqual StatusCodes.OK + } + _ <- permissionDsl.addPermissions(Permission(storageName, "read"), Permission(storageName, "write")) + _ <- deltaClient.post[Json](s"/storages/$fullId", payload2, Coyote) { (_, response) => + response.status shouldEqual StatusCodes.Created + } + storageId2 = s"${storageId}2" + _ <- deltaClient.get[Json](s"/storages/$fullId/nxv:$storageId2", Coyote) { (json, response) => + val expected = storageResponse(fullId, storageId2, "s3/read", "s3/write") + .deepMerge(Json.obj("region" -> Json.fromString("eu-west-2"))) + filterMetadataKeys(json) should equalIgnoreArrayOrder(expected) + response.status shouldEqual StatusCodes.OK + } } yield succeed } @@ -153,7 +147,7 @@ class S3StorageSpec extends StorageSpec { "path" -> Json.fromString(logoKey), "mediaType" -> Json.fromString("image/png") ) - + val fileId = s"${config.deltaUri}/resources/$fullId/_/logo.png" deltaClient.put[Json](s"/files/$fullId/logo.png?storage=nxv:${storageId}2", payload, Coyote) { (json, response) => response.status shouldEqual StatusCodes.Created filterMetadataKeys(json) shouldEqual @@ -162,6 +156,7 @@ class S3StorageSpec extends StorageSpec { replacements( Coyote, "projId" -> fullId, + "self" -> fileSelf(fullId, fileId), "endpoint" -> s3Endpoint, "endpointBucket" -> s3BucketEndpoint, "key" -> logoKey diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/SparqlViewsSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/SparqlViewsSpec.scala index 5fe32baa85..7136cc572b 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/SparqlViewsSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/SparqlViewsSpec.scala @@ -70,13 +70,13 @@ class SparqlViewsSpec extends BaseSpec with EitherValuable with CirceEq { "get the created SparqlView" in { deltaClient.get[Json](s"/views/$fullId/test-resource:cell-view", ScoobyDoo) { (json, response) => response.status shouldEqual StatusCodes.OK - + val viewId = "https://dev.nexus.test.com/simplified-resource/cell-view" val expected = jsonContentOf( "/kg/views/sparql-view-response.json", replacements( ScoobyDoo, "id" -> "https://dev.nexus.test.com/simplified-resource/cell-view", - "resources" -> s"${config.deltaUri}/views/$fullId/test-resource:cell-view", + "self" -> viewSelf(fullId, viewId), "project-parent" -> s"${config.deltaUri}/projects/$fullId" ): _* ) @@ -96,12 +96,13 @@ class SparqlViewsSpec extends BaseSpec with EitherValuable with CirceEq { "get an AggregateSparqlView" in { deltaClient.get[Json](s"/views/$fullId2/test-resource:agg-cell-view", ScoobyDoo) { (json, response) => response.status shouldEqual StatusCodes.OK + val viewId = "https://dev.nexus.test.com/simplified-resource/agg-cell-view" val expected = jsonContentOf( "/kg/views/agg-sparql-view-response.json", replacements( ScoobyDoo, - "id" -> "https://dev.nexus.test.com/simplified-resource/agg-cell-view", - "resources" -> s"${config.deltaUri}/views/$fullId2/test-resource:agg-cell-view", + "id" -> viewId, + "resources" -> viewSelf(fullId2, viewId), "project-parent" -> s"${config.deltaUri}/projects/$fullId2", "project1" -> fullId, "project2" -> fullId2 diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/StorageSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/StorageSpec.scala index 29b7455cdc..680a1c7490 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/StorageSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/kg/StorageSpec.scala @@ -1,7 +1,7 @@ package ch.epfl.bluebrain.nexus.tests.kg import akka.http.scaladsl.model.headers.{ContentDispositionTypes, HttpEncodings} -import akka.http.scaladsl.model.{ContentType, ContentTypes, HttpResponse, StatusCodes} +import akka.http.scaladsl.model.{ContentType, ContentTypes, HttpResponse, StatusCodes, Uri} import akka.util.ByteString import ch.epfl.bluebrain.nexus.testkit.CirceEq import ch.epfl.bluebrain.nexus.tests.BaseSpec @@ -31,6 +31,8 @@ abstract class StorageSpec extends BaseSpec with CirceEq { private[tests] val projId = genId() private[tests] val fullId = s"$orgId/$projId" + private[tests] val attachmentPrefix = s"${config.deltaUri}/resources/$fullId/_/" + def storageName: String def storageType: String @@ -41,6 +43,13 @@ abstract class StorageSpec extends BaseSpec with CirceEq { def createStorages: Task[Assertion] + protected def fileSelf(project: String, id: String): String = { + val uri = Uri(s"${config.deltaUri}/files/$project") + uri.copy(path = uri.path / id).toString + } + + private[tests] val fileSelfPrefix = fileSelf(fullId, attachmentPrefix) + "creating projects" should { "add necessary ACLs for user" in { @@ -202,12 +211,14 @@ abstract class StorageSpec extends BaseSpec with CirceEq { } "fetch attachment metadata" in { + val id = s"${attachmentPrefix}attachment.json" val expected = jsonContentOf( "/kg/files/attachment-metadata.json", replacements( Coyote, - "id" -> s"${config.deltaUri}/resources/$fullId/_/attachment.json", - "filename" -> s"attachment.json", + "id" -> id, + "self" -> fileSelf(fullId, id), + "filename" -> "attachment.json", "storageId" -> storageId, "storageType" -> storageType, "projId" -> s"$fullId", @@ -290,11 +301,14 @@ abstract class StorageSpec extends BaseSpec with CirceEq { } "fetch second attachment metadata" in { + val id = s"${attachmentPrefix}attachment2" val expected = jsonContentOf( "/kg/files/attachment2-metadata.json", replacements( Coyote, + "id" -> id, "storageId" -> storageId, + "self" -> fileSelf(fullId, id), "storageType" -> storageType, "projId" -> s"$fullId", "project" -> s"${config.deltaUri}/projects/$fullId", @@ -334,9 +348,10 @@ abstract class StorageSpec extends BaseSpec with CirceEq { response.status shouldEqual StatusCodes.OK val mapping = replacements( Coyote, - "project" -> fullId, - "storageId" -> storageId, - "storageType" -> storageType + "project" -> fullId, + "fileSelfPrefix" -> fileSelfPrefix, + "storageId" -> storageId, + "storageType" -> storageType ) val expected = jsonContentOf("/kg/files/list.json", mapping: _*) filterSearchMetadata @@ -345,6 +360,7 @@ abstract class StorageSpec extends BaseSpec with CirceEq { } "query the default sparql view for files" in eventually { + val id = s"http://delta:8080/v1/resources/$fullId/_/attachment.json" val query = s""" |prefix nxv: @@ -367,7 +383,7 @@ abstract class StorageSpec extends BaseSpec with CirceEq { | :incoming ?incoming ; | :outgoing ?outgoing ; |} WHERE { - | BIND( as ?id) . + | BIND(<$id> as ?id) . | | ?id a ?type . | ?id nxv:filename ?filename; @@ -394,6 +410,7 @@ abstract class StorageSpec extends BaseSpec with CirceEq { val mapping = replacements( Coyote, "project" -> fullId, + "self" -> fileSelf(fullId, id), "storageId" -> storageId ) val expected = jsonContentOf("/kg/files/sparql.json", mapping: _*) diff --git a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/plugins/blazegraph/IncomingOutgoingBlazegraphSpec.scala b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/plugins/blazegraph/IncomingOutgoingBlazegraphSpec.scala index 55b6ef5bd1..a2d6eba18d 100644 --- a/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/plugins/blazegraph/IncomingOutgoingBlazegraphSpec.scala +++ b/tests/src/test/scala/ch/epfl/bluebrain/nexus/tests/plugins/blazegraph/IncomingOutgoingBlazegraphSpec.scala @@ -94,10 +94,10 @@ class IncomingOutgoingBlazegraphSpec extends BaseSpec with EitherValuable { "return incoming references" in { deltaClient.get[Json](s"/resources/$orgLabel/$projLabel/_/radar/incoming", Radar) { (json, response) => response.status shouldEqual StatusCodes.OK - root._total.long.getOption(json).value shouldEqual 2L + root._total.long.getOption(json).value shouldEqual 1L val refs = root._results.json.getOption(json).value.as[List[Reference]].rightValue val resBase = s"${config.deltaUri}/resources/$orgLabel/$projLabel/_" - refs.map(_.`@id`) shouldEqual List(s"$resBase/radar", s"$resBase/hawkeye") + refs.map(_.`@id`) shouldEqual List(s"$resBase/hawkeye") } }