Skip to content

Commit

Permalink
Migrate projects to Cats Effect (#4446)
Browse files Browse the repository at this point in the history
  • Loading branch information
olivergrabinski authored Nov 1, 2023
1 parent 09106ca commit feeea5e
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ package ch.epfl.bluebrain.nexus.delta.routes
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import cats.data.OptionT
import cats.effect.{ContextShift, IO}
import cats.implicits._
import ch.epfl.bluebrain.nexus.delta.kernel.effect.migration._
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.rdf.utils.JsonKeyOrdering
import ch.epfl.bluebrain.nexus.delta.sdk._
import ch.epfl.bluebrain.nexus.delta.kernel.effect.migration._
import ch.epfl.bluebrain.nexus.delta.sdk.acls.AclCheck
import ch.epfl.bluebrain.nexus.delta.sdk.ce.DeltaDirectives._
import ch.epfl.bluebrain.nexus.delta.sdk.circe.CirceUnmarshalling
import ch.epfl.bluebrain.nexus.delta.sdk.directives.DeltaDirectives._
import ch.epfl.bluebrain.nexus.delta.sdk.directives.{AuthDirectives, DeltaSchemeDirectives}
import ch.epfl.bluebrain.nexus.delta.sdk.fusion.FusionConfig
import ch.epfl.bluebrain.nexus.delta.sdk.identities.Identities
Expand All @@ -27,8 +29,6 @@ import ch.epfl.bluebrain.nexus.delta.sdk.projects.model._
import ch.epfl.bluebrain.nexus.delta.sdk.projects.{Projects, ProjectsConfig, ProjectsStatistics}
import ch.epfl.bluebrain.nexus.delta.sdk.provisioning.ProjectProvisioning
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.bio.IO
import monix.execution.Scheduler

/**
* The project routes
Expand All @@ -53,10 +53,10 @@ final class ProjectsRoutes(
)(implicit
baseUri: BaseUri,
config: ProjectsConfig,
s: Scheduler,
cr: RemoteContextResolution,
ordering: JsonKeyOrdering,
fusionConfig: FusionConfig
fusionConfig: FusionConfig,
contextShift: ContextShift[IO]
) extends AuthDirectives(identities, aclCheck)
with CirceUnmarshalling {

Expand All @@ -82,7 +82,7 @@ final class ProjectsRoutes(
}

private def provisionProject(implicit caller: Caller): Directive0 = onSuccess(
projectProvisioning(caller.subject).runToFuture
projectProvisioning(caller.subject).unsafeToFuture()
)

def routes: Route =
Expand Down Expand Up @@ -110,14 +110,19 @@ final class ProjectsRoutes(
// Create project
authorizeFor(ref, projectsPermissions.create).apply {
entity(as[ProjectFields]) { fields =>
emit(StatusCodes.Created, projects.create(ref, fields).mapValue(_.metadata))
emit(
StatusCodes.Created,
projects.create(ref, fields).mapValue(_.metadata).attemptNarrow[ProjectRejection]
)
}
}
case Some(rev) =>
// Update project
authorizeFor(ref, projectsPermissions.write).apply {
entity(as[ProjectFields]) { fields =>
emit(projects.update(ref, rev, fields).mapValue(_.metadata))
emit(
projects.update(ref, rev, fields).mapValue(_.metadata).attemptNarrow[ProjectRejection]
)
}
}
}
Expand All @@ -126,13 +131,13 @@ final class ProjectsRoutes(
parameter("rev".as[Int].?) {
case Some(rev) => // Fetch project at specific revision
authorizeFor(ref, projectsPermissions.read).apply {
emit(projects.fetchAt(ref, rev).leftWiden[ProjectRejection])
emit(projects.fetchAt(ref, rev).attemptNarrow[ProjectRejection])
}
case None => // Fetch project
emitOrFusionRedirect(
ref,
authorizeFor(ref, projectsPermissions.read).apply {
emit(projects.fetch(ref).leftWiden[ProjectRejection])
emit(projects.fetch(ref).attemptNarrow[ProjectRejection])
}
)
}
Expand All @@ -142,11 +147,11 @@ final class ProjectsRoutes(
parameters("rev".as[Int], "prune".?(false)) {
case (rev, true) =>
authorizeFor(ref, projectsPermissions.delete).apply {
emit(projects.delete(ref, rev).mapValue(_.metadata))
emit(projects.delete(ref, rev).mapValue(_.metadata).attemptNarrow[ProjectRejection])
}
case (rev, false) =>
authorizeFor(ref, projectsPermissions.write).apply {
emit(projects.deprecate(ref, rev).mapValue(_.metadata))
emit(projects.deprecate(ref, rev).mapValue(_.metadata).attemptNarrow[ProjectRejection])
}
}
}
Expand All @@ -156,8 +161,9 @@ final class ProjectsRoutes(
// Project statistics
(pathPrefix("statistics") & get & pathEndOrSingleSlash) {
authorizeFor(ref, resources.read).apply {
val stats = projectsStatistics.get(ref).toCatsIO
emit(
IO.fromOptionEval(projectsStatistics.get(ref), ProjectNotFound(ref)).leftWiden[ProjectRejection]
OptionT(stats).toRight[ProjectRejection](ProjectNotFound(ref)).value
)
}
}
Expand Down Expand Up @@ -195,10 +201,10 @@ object ProjectsRoutes {
)(implicit
baseUri: BaseUri,
config: ProjectsConfig,
s: Scheduler,
cr: RemoteContextResolution,
ordering: JsonKeyOrdering,
fusionConfig: FusionConfig
fusionConfig: FusionConfig,
contextShift: ContextShift[IO]
): Route =
new ProjectsRoutes(identities, aclCheck, projects, projectsStatistics, projectProvisioning, schemeDirectives).routes

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package ch.epfl.bluebrain.nexus.delta.wiring

import cats.effect.{Clock, IO}
import cats.effect.{Clock, ContextShift, IO}
import cats.implicits._
import ch.epfl.bluebrain.nexus.delta.Main.pluginsMaxPriority
import ch.epfl.bluebrain.nexus.delta.config.AppConfig
import ch.epfl.bluebrain.nexus.delta.kernel.effect.migration.toMonixBIOOps
import ch.epfl.bluebrain.nexus.delta.kernel.effect.migration._
import ch.epfl.bluebrain.nexus.delta.kernel.utils.UUIDF
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.ProjectsRoutes
import ch.epfl.bluebrain.nexus.delta.kernel.effect.migration._
import ch.epfl.bluebrain.nexus.delta.sdk._
import ch.epfl.bluebrain.nexus.delta.sdk.acls.{AclCheck, Acls}
import ch.epfl.bluebrain.nexus.delta.sdk.deletion.{ProjectDeletionCoordinator, ProjectDeletionTask}
Expand Down Expand Up @@ -59,7 +58,7 @@ object ProjectsModule extends ModuleDef {
mappings: ApiMappingsCollection,
xas: Transactors,
baseUri: BaseUri,
clock: Clock[UIO],
clock: Clock[IO],
uuidF: UUIDF
) =>
IO.pure(
Expand All @@ -84,8 +83,14 @@ object ProjectsModule extends ModuleDef {
}

make[ProjectProvisioning].from {
(acls: Acls, projects: Projects, config: AppConfig, serviceAccount: ServiceAccount) =>
ProjectProvisioning(acls, projects, config.automaticProvisioning, serviceAccount)
(
acls: Acls,
projects: Projects,
config: AppConfig,
serviceAccount: ServiceAccount,
contextShift: ContextShift[IO]
) =>
ProjectProvisioning(acls, projects, config.automaticProvisioning, serviceAccount)(contextShift)
}

make[FetchContext[ContextRejection]].fromEffect {
Expand Down Expand Up @@ -134,18 +139,18 @@ object ProjectsModule extends ModuleDef {
projectProvisioning: ProjectProvisioning,
schemeDirectives: DeltaSchemeDirectives,
baseUri: BaseUri,
s: Scheduler,
cr: RemoteContextResolution @Id("aggregate"),
ordering: JsonKeyOrdering,
fusionConfig: FusionConfig
fusionConfig: FusionConfig,
contextShift: ContextShift[IO]
) =>
new ProjectsRoutes(identities, aclCheck, projects, projectsStatistics, projectProvisioning, schemeDirectives)(
baseUri,
config.projects,
s,
cr,
ordering,
fusionConfig
fusionConfig,
contextShift
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ object ValidateCompositeView {
aclCheck.authorizeForOr(cpSource.project, events.read, cpSource.identities)(CrossProjectSourceForbidden(cpSource))

def validateProject(cpSource: CrossProjectSource) =
projects.fetch(cpSource.project).mapError(_ => CrossProjectSourceProjectNotFound(cpSource)).void
projects.fetch(cpSource.project).orRaise(CrossProjectSourceProjectNotFound(cpSource)).void

def validatePermission(permission: Permission) =
fetchPermissions.flatMap { perms =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class ProjectDeletionRunner(projects: Projects, config: ProjectDeletionConfig, p

private def deleteProject(pr: ProjectResource): IO[Unit] = {
implicit val caller: Subject = Identity.Anonymous
toCatsIO(projects.delete(pr.value.ref, pr.rev))
projects
.delete(pr.value.ref, pr.rev)
.handleErrorWith(e => logger.error(s"Error deleting project from plugin: $e"))
.void
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ object Acls {
def projectDeletionTask(acls: Acls): ProjectDeletionTask = new ProjectDeletionTask {
override def apply(project: ProjectRef)(implicit subject: Subject): Task[ProjectDeletionReport.Stage] = {
val report = ProjectDeletionReport.Stage("acls", "The acl has been deleted.")
acls.purge(project).as(report).toTask
acls.purge(project).toTask.as(report)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ch.epfl.bluebrain.nexus.delta.sdk.marshalling.HttpResponseFields
import ch.epfl.bluebrain.nexus.delta.sdk.organizations.Organizations
import ch.epfl.bluebrain.nexus.delta.sdk.organizations.model.OrganizationRejection
import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.ProjectRejection._
import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectContext}
import ch.epfl.bluebrain.nexus.delta.sdk.projects.model.{ApiMappings, ProjectContext, ProjectRejection}
import ch.epfl.bluebrain.nexus.delta.sdk.quotas.Quotas
import ch.epfl.bluebrain.nexus.delta.sdk.quotas.model.QuotaRejection
import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Subject
Expand Down Expand Up @@ -149,14 +149,14 @@ object FetchContext {
apply(
organizations.fetchActiveOrganization(_).void.toBIO[OrganizationRejection],
projects.defaultApiMappings,
projects.fetch,
projects.fetch(_).toBIO[ProjectRejection],
quotas
)

def apply(
fetchActiveOrganization: Label => IO[OrganizationRejection, Unit],
dam: ApiMappings,
fetchProject: ProjectRef => IO[ProjectNotFound, ProjectResource],
fetchProject: ProjectRef => IO[ProjectRejection, ProjectResource],
quotas: Quotas
): FetchContext[ContextRejection] =
new FetchContext[ContextRejection] {
Expand Down
Loading

0 comments on commit feeea5e

Please sign in to comment.