-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
02471bf
commit 50d2688
Showing
23 changed files
with
626 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,6 +125,7 @@ app { | |
"version/read", | ||
"quotas/read", | ||
"supervision/read", | ||
"typehierarchy/write" | ||
"export/run" | ||
] | ||
|
||
|
65 changes: 65 additions & 0 deletions
65
delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/routes/TypeHierarchyRoutes.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package ch.epfl.bluebrain.nexus.delta.routes | ||
|
||
import akka.http.scaladsl.model.StatusCodes | ||
import akka.http.scaladsl.server.Route | ||
import cats.implicits.catsSyntaxApplicativeError | ||
import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.RemoteContextResolution | ||
import ch.epfl.bluebrain.nexus.delta.rdf.utils.JsonKeyOrdering | ||
import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclCheck | ||
import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress | ||
import ch.epfl.bluebrain.nexus.delta.sdk.circe.CirceUnmarshalling | ||
import ch.epfl.bluebrain.nexus.delta.sdk.directives.AuthDirectives | ||
import ch.epfl.bluebrain.nexus.delta.sdk.directives.DeltaDirectives._ | ||
import ch.epfl.bluebrain.nexus.delta.sdk.identities.Identities | ||
import ch.epfl.bluebrain.nexus.delta.sdk.implicits._ | ||
import ch.epfl.bluebrain.nexus.delta.sdk.model.BaseUri | ||
import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.typehierarchy | ||
import ch.epfl.bluebrain.nexus.delta.sdk.typehierarchy.{TypeHierarchy => TypeHierarchyModel} | ||
import ch.epfl.bluebrain.nexus.delta.sdk.typehierarchy.model.{TypeHierarchy, TypeHierarchyRejection} | ||
|
||
final class TypeHierarchyRoutes( | ||
typeHierarchy: TypeHierarchyModel, | ||
identities: Identities, | ||
aclCheck: AclCheck | ||
)(implicit | ||
baseUri: BaseUri, | ||
cr: RemoteContextResolution, | ||
ordering: JsonKeyOrdering | ||
) extends AuthDirectives(identities, aclCheck) | ||
with CirceUnmarshalling { | ||
|
||
def routes: Route = | ||
baseUriPrefix(baseUri.prefix) { | ||
extractCaller { implicit caller => | ||
pathPrefix("type-hierarchy") { | ||
concat( | ||
// Fetch using the revision | ||
(get & parameter("rev".as[Int]) & pathEndOrSingleSlash) { rev => | ||
emit(typeHierarchy.fetch(rev).attemptNarrow[TypeHierarchyRejection]) | ||
}, | ||
// Fetch the type hierarchy | ||
(get & pathEndOrSingleSlash) { | ||
emit(typeHierarchy.fetch.attemptNarrow[TypeHierarchyRejection]) | ||
}, | ||
// Create the type hierarchy | ||
(post & pathEndOrSingleSlash) { | ||
entity(as[TypeHierarchy]) { payload => | ||
authorizeFor(AclAddress.Root, typehierarchy.write).apply { | ||
emit(StatusCodes.Created, typeHierarchy.create(payload.mapping).attemptNarrow[TypeHierarchyRejection]) | ||
} | ||
} | ||
}, | ||
// Update the type hierarchy | ||
(put & parameter("rev".as[Int]) & pathEndOrSingleSlash) { rev => | ||
entity(as[TypeHierarchy]) { payload => | ||
authorizeFor(AclAddress.Root, typehierarchy.write).apply { | ||
emit(typeHierarchy.update(payload.mapping, rev).attemptNarrow[TypeHierarchyRejection]) | ||
} | ||
} | ||
} | ||
) | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
delta/app/src/main/scala/ch/epfl/bluebrain/nexus/delta/wiring/TypeHierarchyModule.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package ch.epfl.bluebrain.nexus.delta.wiring | ||
|
||
import cats.effect.{Clock, IO} | ||
import ch.epfl.bluebrain.nexus.delta.Main.pluginsMaxPriority | ||
import ch.epfl.bluebrain.nexus.delta.config.AppConfig | ||
import ch.epfl.bluebrain.nexus.delta.kernel.utils.ClasspathResourceLoader | ||
import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.contexts | ||
import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, RemoteContextResolution} | ||
import ch.epfl.bluebrain.nexus.delta.rdf.utils.JsonKeyOrdering | ||
import ch.epfl.bluebrain.nexus.delta.routes.TypeHierarchyRoutes | ||
import ch.epfl.bluebrain.nexus.delta.sdk.PriorityRoute | ||
import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclCheck | ||
import ch.epfl.bluebrain.nexus.delta.sdk.identities.Identities | ||
import ch.epfl.bluebrain.nexus.delta.sdk.typehierarchy.TypeHierarchy | ||
import ch.epfl.bluebrain.nexus.delta.sourcing.Transactors | ||
import izumi.distage.model.definition.{Id, ModuleDef} | ||
|
||
object TypeHierarchyModule extends ModuleDef { | ||
|
||
implicit private val loader: ClasspathResourceLoader = ClasspathResourceLoader.withContext(getClass) | ||
|
||
make[TypeHierarchy].from { (xas: Transactors, config: AppConfig, clock: Clock[IO]) => | ||
TypeHierarchy(xas, config.typeHierarchy, clock) | ||
} | ||
|
||
make[TypeHierarchyRoutes].from { | ||
( | ||
identities: Identities, | ||
typeHierarchy: TypeHierarchy, | ||
aclCheck: AclCheck, | ||
config: AppConfig, | ||
cr: RemoteContextResolution @Id("aggregate"), | ||
ordering: JsonKeyOrdering | ||
) => | ||
new TypeHierarchyRoutes( | ||
typeHierarchy, | ||
identities, | ||
aclCheck | ||
)(config.http.baseUri, cr, ordering) | ||
} | ||
|
||
many[RemoteContextResolution].addEffect( | ||
for { | ||
typeHierarchyCtx <- ContextValue.fromFile("contexts/type-hierarchy.json") | ||
} yield RemoteContextResolution.fixed( | ||
contexts.typeHierarchy -> typeHierarchyCtx | ||
) | ||
) | ||
|
||
many[PriorityRoute].add { (route: TypeHierarchyRoutes) => | ||
PriorityRoute(pluginsMaxPriority + 14, route.routes, requiresStrictEntity = true) | ||
} | ||
|
||
} |
134 changes: 134 additions & 0 deletions
134
delta/app/src/test/scala/ch/epfl/bluebrain/nexus/delta/routes/TypeHierarchyRoutesSpec.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package ch.epfl.bluebrain.nexus.delta.routes | ||
|
||
import akka.http.scaladsl.model.StatusCodes | ||
import akka.http.scaladsl.server.Route | ||
import cats.effect.{IO, Ref} | ||
import ch.epfl.bluebrain.nexus.delta.rdf.syntax.iriStringContextSyntax | ||
import ch.epfl.bluebrain.nexus.delta.sdk.TypeHierarchyResource | ||
import ch.epfl.bluebrain.nexus.delta.sdk.acls.model.AclAddress | ||
import ch.epfl.bluebrain.nexus.delta.sdk.permissions.Permissions.typehierarchy | ||
import ch.epfl.bluebrain.nexus.delta.sdk.typehierarchy.TypeHierarchy | ||
import ch.epfl.bluebrain.nexus.delta.sdk.typehierarchy.model.TypeHierarchy.TypeHierarchyMapping | ||
import ch.epfl.bluebrain.nexus.delta.sdk.typehierarchy.model.TypeHierarchyRejection.TypeHierarchyDoesNotExist | ||
import ch.epfl.bluebrain.nexus.delta.sdk.typehierarchy.model.{TypeHierarchy => TypeHierarchyModel, TypeHierarchyState} | ||
import ch.epfl.bluebrain.nexus.delta.sdk.utils.BaseRouteSpec | ||
import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.User | ||
import ch.epfl.bluebrain.nexus.delta.sourcing.model.{Identity, Label} | ||
import io.circe.syntax.EncoderOps | ||
import org.scalatest.{Assertion, BeforeAndAfterEach} | ||
|
||
import java.time.Instant | ||
|
||
class TypeHierarchyRoutesSpec extends BaseRouteSpec with BeforeAndAfterEach { | ||
|
||
private val typeHierarchyWriter = User("superUser", Label.unsafe(genString())) | ||
private val (aclCheck, identities) = usersFixture( | ||
(typeHierarchyWriter, AclAddress.Root, Set(typehierarchy.write)) | ||
) | ||
|
||
private val typeHierarchyRef = Ref.unsafe[IO, Option[TypeHierarchyResource]](None) | ||
|
||
private val typeHierarchy = new TypeHierarchy { | ||
override def create( | ||
mapping: TypeHierarchyMapping | ||
)(implicit subject: Identity.Subject): IO[TypeHierarchyResource] = { | ||
typeHierarchyRef.set(Some(typeHierarchyResource(rev = 1))) >> | ||
IO.pure(typeHierarchyResource(rev = 1)) | ||
} | ||
|
||
override def update(mapping: TypeHierarchyMapping, rev: Int)(implicit | ||
subject: Identity.Subject | ||
): IO[TypeHierarchyResource] = | ||
typeHierarchyRef | ||
.getAndSet(Some(typeHierarchyResource(rev = rev + 1))) | ||
.flatMap(IO.fromOption(_)(TypeHierarchyDoesNotExist)) | ||
|
||
override def fetch: IO[TypeHierarchyResource] = | ||
typeHierarchyRef.get.flatMap(IO.fromOption(_)(TypeHierarchyDoesNotExist)) | ||
|
||
override def fetch(rev: Int): IO[TypeHierarchyResource] = | ||
typeHierarchyRef.get.flatMap(IO.fromOption(_)(TypeHierarchyDoesNotExist)) | ||
} | ||
|
||
private val routes = Route.seal( | ||
new TypeHierarchyRoutes( | ||
typeHierarchy, | ||
identities, | ||
aclCheck | ||
).routes | ||
) | ||
|
||
private val mapping = Map( | ||
iri"https://schema.org/Movie" -> Set(iri"https://schema.org/CreativeWork", iri"https://schema.org/Thing") | ||
) | ||
private val jsonMapping = TypeHierarchyModel(mapping).asJson | ||
|
||
override def beforeEach(): Unit = { | ||
super.beforeAll() | ||
typeHierarchyRef.set(None).accepted | ||
} | ||
|
||
"The TypeHierarchyRoutes" should { | ||
"fail to create the type hierarchy without permissions" in { | ||
Post("/v1/type-hierarchy", jsonMapping.toEntity) ~> routes ~> check { | ||
response.shouldBeForbidden | ||
typeHierarchyRef.get.accepted shouldEqual None | ||
} | ||
} | ||
|
||
"succeed to create the type hierarchy with write permissions" in { | ||
Post("/v1/type-hierarchy", jsonMapping.toEntity) ~> as(typeHierarchyWriter) ~> routes ~> check { | ||
status shouldEqual StatusCodes.Created | ||
typeHierarchyRef.get.accepted shouldEqual Some(typeHierarchyResource(rev = 1)) | ||
} | ||
} | ||
|
||
"return the type hierarchy anonymously" in { | ||
givenATypeHierarchyExists { | ||
Get("/v1/type-hierarchy") ~> routes ~> check { | ||
status shouldEqual StatusCodes.OK | ||
typeHierarchyRef.get.accepted shouldEqual Some(typeHierarchyResource(rev = 1)) | ||
} | ||
} | ||
} | ||
|
||
"fail to update the type hierarchy without permissions" in { | ||
givenATypeHierarchyExists { | ||
Put("/v1/type-hierarchy?rev=1", jsonMapping.toEntity) ~> routes ~> check { | ||
response.shouldBeForbidden | ||
typeHierarchyRef.get.accepted shouldEqual Some(typeHierarchyResource(rev = 1)) | ||
} | ||
} | ||
} | ||
|
||
"succeed to update the type hierarchy with write permissions" in { | ||
givenATypeHierarchyExists { | ||
Put("/v1/type-hierarchy?rev=1", jsonMapping.toEntity) ~> as(typeHierarchyWriter) ~> routes ~> check { | ||
status shouldEqual StatusCodes.OK | ||
typeHierarchyRef.get.accepted shouldEqual Some(typeHierarchyResource(rev = 2)) | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
def givenATypeHierarchyExists(test: => Assertion): Assertion = | ||
Post("/v1/type-hierarchy", jsonMapping.toEntity) ~> as(typeHierarchyWriter) ~> routes ~> check { | ||
status shouldEqual StatusCodes.Created | ||
test | ||
} | ||
|
||
private def typeHierarchyResource(rev: Int) = | ||
TypeHierarchyState( | ||
Map( | ||
iri"https://schema.org/Movie" -> Set(iri"https://schema.org/CreativeWork", iri"https://schema.org/Thing") | ||
), | ||
rev = rev, | ||
deprecated = false, | ||
createdAt = Instant.EPOCH, | ||
createdBy = typeHierarchyWriter, | ||
updatedAt = Instant.EPOCH, | ||
updatedBy = typeHierarchyWriter | ||
).toResource | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"@context": { | ||
"@vocab": "https://bluebrain.github.io/nexus/vocabulary/", | ||
"mapping": "https://bluebrain.github.io/nexus/vocabulary/mapping" | ||
}, | ||
"@id": "https://bluebrain.github.io/nexus/contexts/type-hierarchy.json" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
docs/src/main/paradox/docs/delta/api/assets/type-hierarchy/create.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
curl -X POST \ | ||
-H "Content-Type: application/json" \ | ||
"http://localhost:8080/v1/type-hierarchy" \ | ||
-d \ | ||
'{ | ||
"mapping": { | ||
"https://schema.org/VideoGame": [ | ||
"https://schema.org/SoftwareApplication", | ||
"https://schema.org/CreativeWork", | ||
"https://schema.org/Thing" | ||
] | ||
} | ||
}' |
Oops, something went wrong.