Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Introduce /admin/maintenance and expose fix top left maintenance action DEV-2805 #2877

Merged
merged 42 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
26df5d0
refactor: Introduce tapir on Akka
seakayone Oct 5, 2023
0401dc6
Turn error response to Json
seakayone Oct 5, 2023
081443a
Turn error response to Json and add metrics
seakayone Oct 5, 2023
9820928
Extract interpreter
seakayone Oct 5, 2023
3485a1d
add secure endpoints (wip: only bearer for now)
seakayone Oct 5, 2023
c3357d4
Add cookie auth
seakayone Oct 5, 2023
34777ec
Add basic auth
seakayone Oct 5, 2023
2302181
add admin members endpoint
seakayone Oct 5, 2023
fe42d52
add delete project endpoint
seakayone Oct 5, 2023
0715844
add delete project endpoint
seakayone Oct 5, 2023
e68b143
add export and create project endpoint
seakayone Oct 6, 2023
54b10b4
add update project route
seakayone Oct 6, 2023
47cd2d8
clarify ProjectsRestService methods naming
seakayone Oct 6, 2023
5dd43cc
fix test
seakayone Oct 6, 2023
acfeb77
rm index.html
seakayone Oct 6, 2023
e5e0467
Merge branch 'main' into chore/add-tapir-dependencies
seakayone Oct 6, 2023
d6456f3
Merge branch 'chore/add-tapir-dependencies' into refactor/add-secure-…
seakayone Oct 6, 2023
290e112
add admin/projects/export endpoint
seakayone Oct 6, 2023
68b7767
add set restricted view size endpoints to tapir/pekko
seakayone Oct 6, 2023
18716ae
add copyright header
seakayone Oct 6, 2023
74a5496
Merge branch 'chore/add-tapir-dependencies' into refactor/add-secure-…
seakayone Oct 6, 2023
281fea6
add post import endpoint
seakayone Oct 6, 2023
bcd49f2
cleanup
seakayone Oct 6, 2023
b6abc25
cleanup
seakayone Oct 6, 2023
fcc4a6f
cleanup, remove duplicate "Payload/Request" objects
seakayone Oct 6, 2023
0657874
Merge branch 'main' into chore/add-tapir-dependencies
seakayone Oct 11, 2023
95d48c8
Rename it to handler
seakayone Oct 11, 2023
d80861a
Merge branch 'chore/add-tapir-dependencies' into refactor/add-secure-…
seakayone Oct 11, 2023
893a17e
move ProjectEndpoints to admin.api package
seakayone Oct 11, 2023
7fd19ff
move BaseEndpoints to common.api package
seakayone Oct 11, 2023
ea54e56
move HandlerMapper and TapirToPekkoInterpreter to common.api package
seakayone Oct 11, 2023
638e47e
move HandlerMapper and TapirToPekkoInterpreter to common.api package
seakayone Oct 11, 2023
cd8b4be
fmt
seakayone Oct 11, 2023
d625f6f
Expose fix top left maintenance action
seakayone Oct 11, 2023
8efd1e6
Merge branch 'main' into feat/expose-topleft-transpose-maintenance
seakayone Oct 11, 2023
7cc13a4
rm doanothing
seakayone Oct 11, 2023
7401c1b
Merge branch 'main' into feat/expose-topleft-transpose-maintenance
seakayone Oct 12, 2023
6bf18e9
fmt headerCreate
seakayone Oct 12, 2023
e93787d
reduce logging for each asset to debug
seakayone Oct 12, 2023
b0e691f
Use IO
seakayone Oct 12, 2023
a3f6999
extract getParamsAs[A]
seakayone Oct 12, 2023
e9e2b14
Merge branch 'main' into feat/expose-topleft-transpose-maintenance
seakayone Oct 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,13 @@ import org.knora.webapi.responders.v2.ontology.OntologyHelpersLive
import org.knora.webapi.routing._
import org.knora.webapi.routing.admin.AuthenticatorService
import org.knora.webapi.routing.admin.ProjectsRouteZ
import org.knora.webapi.slice.admin.api.ProjectsEndpoints
import org.knora.webapi.slice.admin.api.ProjectsEndpointsHandler
import org.knora.webapi.slice.admin.api._
import org.knora.webapi.slice.admin.api.service.MaintenanceRestService
import org.knora.webapi.slice.admin.api.service.ProjectADMRestService
import org.knora.webapi.slice.admin.api.service.ProjectsADMRestServiceLive
import org.knora.webapi.slice.admin.domain.service._
import org.knora.webapi.slice.admin.repo.service.KnoraProjectRepoLive
import org.knora.webapi.slice.common.api.BaseEndpoints
import org.knora.webapi.slice.common.api.HandlerMapperF
import org.knora.webapi.slice.common.api.RestPermissionService
import org.knora.webapi.slice.common.api.RestPermissionServiceLive
import org.knora.webapi.slice.common.api._
import org.knora.webapi.slice.common.repo.service.PredicateObjectMapper
import org.knora.webapi.slice.ontology.api.service.RestCardinalityService
import org.knora.webapi.slice.ontology.api.service.RestCardinalityServiceLive
Expand Down Expand Up @@ -135,7 +132,7 @@ object LayersTest {

private val commonLayersForAllIntegrationTests =
ZLayer.makeSome[CommonR0, CommonR](
HandlerMapperF.layer,
AdminApiRoutes.layer,
ApiRoutes.layer,
AppRouter.layer,
AuthenticationMiddleware.layer,
Expand All @@ -151,6 +148,7 @@ object LayersTest {
DspIngestClientLive.layer,
GravsearchTypeInspectionRunner.layer,
GroupsResponderADMLive.layer,
HandlerMapper.layer,
HttpServer.layer,
HttpServerZ.layer,
IIIFRequestMessageHandlerLive.layer,
Expand All @@ -160,6 +158,10 @@ object LayersTest {
KnoraProjectRepoLive.layer,
ListsResponderADMLive.layer,
ListsResponderV2Live.layer,
MaintenanceEndpoints.layer,
MaintenanceEndpointsHandlers.layer,
MaintenanceRestService.layer,
MaintenanceServiceLive.layer,
MessageRelayLive.layer,
OntologyCacheLive.layer,
OntologyHelpersLive.layer,
Expand Down Expand Up @@ -194,6 +196,7 @@ object LayersTest {
StandoffTagUtilV2Live.layer,
State.layer,
StoresResponderADMLive.layer,
TapirToPekkoInterpreter.layer,
TestClientService.layer,
TriplestoreServiceLive.layer,
UsersResponderADMLive.layer,
Expand Down
17 changes: 10 additions & 7 deletions webapi/src/main/scala/org/knora/webapi/core/LayersLive.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,13 @@ import org.knora.webapi.responders.v2.ontology.OntologyHelpersLive
import org.knora.webapi.routing._
import org.knora.webapi.routing.admin.AuthenticatorService
import org.knora.webapi.routing.admin.ProjectsRouteZ
import org.knora.webapi.slice.admin.api.ProjectsEndpoints
import org.knora.webapi.slice.admin.api.ProjectsEndpointsHandler
import org.knora.webapi.slice.admin.api._
import org.knora.webapi.slice.admin.api.service.MaintenanceRestService
import org.knora.webapi.slice.admin.api.service.ProjectADMRestService
import org.knora.webapi.slice.admin.api.service.ProjectsADMRestServiceLive
import org.knora.webapi.slice.admin.domain.service._
import org.knora.webapi.slice.admin.repo.service.KnoraProjectRepoLive
import org.knora.webapi.slice.common.api.BaseEndpoints
import org.knora.webapi.slice.common.api.HandlerMapperF
import org.knora.webapi.slice.common.api.RestPermissionService
import org.knora.webapi.slice.common.api.RestPermissionServiceLive
import org.knora.webapi.slice.common.api._
import org.knora.webapi.slice.common.repo.service.PredicateObjectMapper
import org.knora.webapi.slice.ontology.api.service.RestCardinalityService
import org.knora.webapi.slice.ontology.api.service.RestCardinalityServiceLive
Expand Down Expand Up @@ -134,6 +131,7 @@ object LayersLive {
val dspLayersLive: ULayer[DspEnvironmentLive] =
ZLayer.make[DspEnvironmentLive](
ActorSystem.layer,
AdminApiRoutes.layer,
ApiRoutes.layer,
AppConfig.layer,
AppRouter.layer,
Expand All @@ -150,7 +148,7 @@ object LayersLive {
DspIngestClientLive.layer,
GravsearchTypeInspectionRunner.layer,
GroupsResponderADMLive.layer,
HandlerMapperF.layer,
HandlerMapper.layer,
HttpServer.layer,
HttpServerZ.layer, // this is the new ZIO HTTP server layer
IIIFRequestMessageHandlerLive.layer,
Expand All @@ -162,6 +160,10 @@ object LayersLive {
KnoraProjectRepoLive.layer,
ListsResponderADMLive.layer,
ListsResponderV2Live.layer,
MaintenanceEndpoints.layer,
MaintenanceEndpointsHandlers.layer,
MaintenanceRestService.layer,
MaintenanceServiceLive.layer,
MessageRelayLive.layer,
OntologyCacheLive.layer,
OntologyHelpersLive.layer,
Expand Down Expand Up @@ -197,6 +199,7 @@ object LayersLive {
State.layer,
StoresResponderADMLive.layer,
StringFormatter.live,
TapirToPekkoInterpreter.layer,
TriplestoreServiceLive.layer,
UsersResponderADMLive.layer,
ValuesResponderV2Live.layer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ trait ProjectsResponderADM {
/**
* Creates a project.
*
* @param projectCreate the new project's information.
* @param createReq the new project's information.
* @param requestingUser the user that is making the request.
* @param apiRequestID the unique api request ID.
* @return A [[ProjectOperationResponseADM]].
Expand All @@ -149,25 +149,25 @@ trait ProjectsResponderADM {
* [[BadRequestException]] In the case when the shortcode is invalid.
*/
def projectCreateRequestADM(
projectCreate: ProjectCreateRequest,
createReq: ProjectCreateRequest,
requestingUser: UserADM,
apiRequestID: UUID
): Task[ProjectOperationResponseADM]

/**
* Update project's basic information.
*
* @param projectIri the IRI of the project.
* @param projectUpdate the update payload.
* @param user the user making the request.
* @param apiRequestID the unique api request ID.
* @param projectIri the IRI of the project.
* @param updateReq the update payload.
* @param user the user making the request.
* @param apiRequestID the unique api request ID.
* @return A [[ProjectOperationResponseADM]].
*
* [[ForbiddenException]] In the case that the user is not allowed to perform the operation.
*/
def changeBasicInformationRequestADM(
projectIri: Iri.ProjectIri,
projectUpdate: ProjectUpdateRequest,
updateReq: ProjectUpdateRequest,
user: UserADM,
apiRequestID: UUID
): Task[ProjectOperationResponseADM]
Expand Down Expand Up @@ -457,17 +457,17 @@ final case class ProjectsResponderADMLive(
/**
* Update project's basic information.
*
* @param projectIri the IRI of the project.
* @param projectUpdate the update payload.
* @param user the user making the request.
* @param apiRequestID the unique api request ID.
* @param projectIri the IRI of the project.
* @param updateReq the update payload.
* @param user the user making the request.
* @param apiRequestID the unique api request ID.
* @return A [[ProjectOperationResponseADM]].
*
* [[ForbiddenException]] In the case that the user is not allowed to perform the operation.
*/
override def changeBasicInformationRequestADM(
projectIri: Iri.ProjectIri,
projectUpdate: ProjectUpdateRequest,
updateReq: ProjectUpdateRequest,
user: UserADM,
apiRequestID: UUID
): Task[ProjectOperationResponseADM] = {
Expand All @@ -477,17 +477,17 @@ final case class ProjectsResponderADMLive(
*/
def changeProjectTask(
projectIri: Iri.ProjectIri,
projectUpdatePayload: ProjectUpdateRequest,
updateReq: ProjectUpdateRequest,
requestingUser: UserADM
): Task[ProjectOperationResponseADM] =
// check if the requesting user is allowed to perform updates
if (!requestingUser.permissions.isProjectAdmin(projectIri.value) && !requestingUser.permissions.isSystemAdmin) {
ZIO.fail(ForbiddenException("Project's information can only be changed by a project or system admin."))
} else {
updateProjectADM(projectIri, projectUpdatePayload)
updateProjectADM(projectIri, updateReq)
}

val task = changeProjectTask(projectIri, projectUpdate, user)
val task = changeProjectTask(projectIri, updateReq, user)
IriLocker.runWithIriLock(apiRequestID, projectIri.value, task)
}

Expand Down Expand Up @@ -652,8 +652,7 @@ final case class ProjectsResponderADMLive(
/**
* Creates a project.
*
* @param projectCreate the new project's information.
*
* @param createReq the new project's information.
* @param requestingUser the user that is making the request.
* @param apiRequestID the unique api request ID.
* @return A [[ProjectOperationResponseADM]].
Expand All @@ -665,7 +664,7 @@ final case class ProjectsResponderADMLive(
* [[BadRequestException]] In the case when the shortcode is invalid.
*/
override def projectCreateRequestADM(
projectCreate: ProjectCreateRequest,
createReq: ProjectCreateRequest,
requestingUser: UserADM,
apiRequestID: UUID
): Task[ProjectOperationResponseADM] = {
Expand Down Expand Up @@ -819,7 +818,7 @@ final case class ProjectsResponderADMLive(

} yield ProjectOperationResponseADM(project = newProjectADM.unescape)

val task = projectCreateTask(projectCreate, requestingUser)
val task = projectCreateTask(createReq, requestingUser)
IriLocker.runWithIriLock(apiRequestID, PROJECTS_GLOBAL_LOCK_IRI, task)
}

Expand Down
45 changes: 16 additions & 29 deletions webapi/src/main/scala/org/knora/webapi/routing/ApiRoutes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,14 @@

package org.knora.webapi.routing

import org.apache.pekko
import org.apache.pekko.actor
import org.apache.pekko.http.cors.scaladsl.CorsDirectives
import org.apache.pekko.http.scaladsl.model.HttpMethods.DELETE
import org.apache.pekko.http.scaladsl.model.HttpMethods.GET
import org.apache.pekko.http.scaladsl.model.HttpMethods.HEAD
import org.apache.pekko.http.scaladsl.model.HttpMethods.OPTIONS
import org.apache.pekko.http.scaladsl.model.HttpMethods.PATCH
import org.apache.pekko.http.scaladsl.model.HttpMethods.POST
import org.apache.pekko.http.scaladsl.model.HttpMethods.PUT
import org.apache.pekko.http.cors.scaladsl.settings.CorsSettings
import org.apache.pekko.http.scaladsl.model.HttpMethods._
import org.apache.pekko.http.scaladsl.server.Directives._
import org.apache.pekko.http.scaladsl.server.Route
import zio._

import scala.concurrent.ExecutionContextExecutor

import org.knora.webapi.config.AppConfig
import org.knora.webapi.core
import org.knora.webapi.core.ActorSystem
Expand All @@ -30,19 +25,14 @@ import org.knora.webapi.responders.v2.ValuesResponderV2
import org.knora.webapi.routing
import org.knora.webapi.routing.admin._
import org.knora.webapi.routing.v2._
import org.knora.webapi.slice.admin.api.AdminApiRoutes
import org.knora.webapi.slice.admin.api.ProjectsEndpointsHandler
import org.knora.webapi.slice.admin.api.service.ProjectADMRestService
import org.knora.webapi.slice.admin.domain.service.KnoraProjectRepo
import org.knora.webapi.slice.common.api.TapirToPekkoInterpreter
import org.knora.webapi.slice.ontology.api.service.RestCardinalityService
import org.knora.webapi.slice.resourceinfo.api.RestResourceInfoService
import org.knora.webapi.slice.resourceinfo.domain.IriConverter

import pekko.actor
import pekko.http.scaladsl.server.Directives._
import pekko.http.scaladsl.server.Route
import pekko.http.cors.scaladsl.settings.CorsSettings

trait ApiRoutes {
val routes: Route
}
Expand All @@ -54,6 +44,7 @@ object ApiRoutes {
*/
val layer: URLayer[
ActorSystem
with AdminApiRoutes
with AppConfig
with AppRouter
with IriConverter
Expand All @@ -71,12 +62,11 @@ object ApiRoutes {
] =
ZLayer {
for {
sys <- ZIO.service[ActorSystem]
router <- ZIO.service[AppRouter]
appConfig <- ZIO.service[AppConfig]
projectsHandler <- ZIO.service[ProjectsEndpointsHandler]
routeData <- ZIO.succeed(KnoraRouteData(sys.system, router.ref, appConfig))
tapirToPekkoRoute = TapirToPekkoInterpreter()(sys.system.dispatcher)
sys <- ZIO.service[ActorSystem]
router <- ZIO.service[AppRouter]
appConfig <- ZIO.service[AppConfig]
adminApiRoutes <- ZIO.service[AdminApiRoutes]
routeData <- ZIO.succeed(KnoraRouteData(sys.system, router.ref, appConfig))
runtime <- ZIO.runtime[
AppConfig
with IriConverter
Expand All @@ -90,7 +80,7 @@ object ApiRoutes {
with core.State
with routing.Authenticator
]
} yield ApiRoutesImpl(routeData, projectsHandler, tapirToPekkoRoute, appConfig, runtime)
} yield ApiRoutesImpl(routeData, adminApiRoutes, appConfig, runtime)
}
}

Expand All @@ -103,8 +93,7 @@ object ApiRoutes {
*/
private final case class ApiRoutesImpl(
routeData: KnoraRouteData,
projectsHandler: ProjectsEndpointsHandler,
tapirToPekkoRoute: TapirToPekkoInterpreter,
adminApiRoutes: AdminApiRoutes,
appConfig: AppConfig,
implicit val runtime: Runtime[
AppConfig
Expand All @@ -122,8 +111,7 @@ private final case class ApiRoutesImpl(
) extends ApiRoutes
with AroundDirectives {

implicit val system: actor.ActorSystem = routeData.system
implicit val executionContext: ExecutionContextExecutor = routeData.system.dispatcher
private implicit val system: actor.ActorSystem = routeData.system

val routes: Route =
logDuration {
Expand All @@ -134,8 +122,7 @@ private final case class ApiRoutesImpl(
.withAllowedMethods(List(GET, PUT, POST, DELETE, PATCH, HEAD, OPTIONS))
) {
DSPApiDirectives.handleErrors(appConfig) {
val adminProjectsRoutes = projectsHandler.allHanders.map(tapirToPekkoRoute.toRoute(_)).reduce(_ ~ _)
adminProjectsRoutes ~
adminApiRoutes.routes.reduce(_ ~ _) ~
AuthenticationRouteV2().makeRoute ~
FilesRouteADM(routeData, runtime).makeRoute ~
GroupsRouteADM(routeData, runtime).makeRoute ~
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright © 2021 - 2023 Swiss National Data and Service Center for the Humanities and/or DaSCH Service Platform contributors.
* SPDX-License-Identifier: Apache-2.0
*/

package org.knora.webapi.slice.admin.api

import org.apache.pekko.http.scaladsl.server.Route
import zio.ZLayer

import org.knora.webapi.slice.common.api.TapirToPekkoInterpreter

final case class AdminApiRoutes(
maintenance: MaintenanceEndpointsHandlers,
project: ProjectsEndpointsHandler,
tapirToPekko: TapirToPekkoInterpreter
) {

private val handlers = maintenance.handlers ++ project.allHanders

val routes: Seq[Route] = handlers.map(tapirToPekko.toRoute(_))
}

object AdminApiRoutes {
val layer = ZLayer.derive[AdminApiRoutes]
}
Loading
Loading