Skip to content

Commit

Permalink
Migrate DELETE /admin/lists/comments/<listIri> to Tapir
Browse files Browse the repository at this point in the history
  • Loading branch information
seakayone committed Feb 1, 2024
1 parent bc04ae5 commit 9d9a8a2
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -955,48 +955,34 @@ class ListsResponderSpec extends CoreSpec with ImplicitSender {

"used to delete list node comments" should {
"do not delete a comment of root list node" in {
val nodeIri = "http://rdfh.ch/lists/0001/testList"
appActor ! ListNodeCommentsDeleteRequestADM(
iri = nodeIri,
requestingUser = SharedTestDataADM.anythingAdminUser
)
expectMsg(
Failure(BadRequestException("Root node comments cannot be deleted."))
val listIri = ListIri.unsafeFrom("http://rdfh.ch/lists/0001/testList")
val exit = UnsafeZioRun.run(ListsResponder.deleteListNodeCommentsADM(listIri))
assertFailsWithA[BadRequestException](
exit,
s"Root node comments cannot be deleted."
)
}

"delete all comments of child node that contains just one comment" in {
val nodeIri = "http://rdfh.ch/lists/0001/testList01"
appActor ! ListNodeCommentsDeleteRequestADM(
iri = nodeIri,
requestingUser = SharedTestDataADM.anythingAdminUser
)
val response: ListNodeCommentsDeleteResponseADM =
expectMsgType[ListNodeCommentsDeleteResponseADM](timeout)
response.nodeIri should be(nodeIri)
val listIri = ListIri.unsafeFrom("http://rdfh.ch/lists/0001/testList01")
val response = UnsafeZioRun.runOrThrow(ListsResponder.deleteListNodeCommentsADM(listIri))
response.nodeIri should be(listIri.value)
response.commentsDeleted should be(true)
}

"delete all comments of child node that contains more than one comment" in {
val nodeIri = "http://rdfh.ch/lists/0001/testList02"
appActor ! ListNodeCommentsDeleteRequestADM(
iri = nodeIri,
requestingUser = SharedTestDataADM.anythingAdminUser
)
val response: ListNodeCommentsDeleteResponseADM =
expectMsgType[ListNodeCommentsDeleteResponseADM](timeout)
response.nodeIri should be(nodeIri)
val listIri = ListIri.unsafeFrom("http://rdfh.ch/lists/0001/testList02")
val response = UnsafeZioRun.runOrThrow(ListsResponder.deleteListNodeCommentsADM(listIri))
response.nodeIri should be(listIri.value)
response.commentsDeleted should be(true)
}

"if reqested list does not have comments, inform there is no comments to delete" in {
val nodeIri = "http://rdfh.ch/lists/0001/testList03"
appActor ! ListNodeCommentsDeleteRequestADM(
iri = nodeIri,
requestingUser = SharedTestDataADM.anythingAdminUser
)
expectMsg(
Failure(BadRequestException(s"Nothing to delete. Node $nodeIri does not have comments."))
"if requested list does not have comments, inform there is no comments to delete" in {
val listIri = ListIri.unsafeFrom("http://rdfh.ch/lists/0001/testList03")
val exit = UnsafeZioRun.run(ListsResponder.deleteListNodeCommentsADM(listIri))
assertFailsWithA[BadRequestException](
exit,
s"Nothing to delete. Node ${listIri.value} does not have comments."
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,17 +190,6 @@ case class ListChildNodeCreateRequestADM(
apiRequestID: UUID
) extends ListsResponderRequestADM

/**
* Requests deletion of all list node comments. A successful response will be a [[ListNodeCommentsDeleteResponseADM]]
*
* @param iri the IRI of the list node (root or child).
* @param requestingUser the user making the request.
*/
case class ListNodeCommentsDeleteRequestADM(
iri: IRI,
requestingUser: User
) extends ListsResponderRequestADM

///////////////////////// Responses

/**
Expand Down Expand Up @@ -400,6 +389,8 @@ sealed trait ListNodeInfoADM {
* @return the comment in the preferred language.
*/
def getCommentInPreferredLanguage(userLang: String, fallbackLang: String): Option[String]

final def hasComments: Boolean = comments.nonEmpty
}

case class ListRootNodeInfoADM(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,9 @@ case class StringLiteralSequenceV2(stringLiterals: Vector[StringLiteralV2]) {
}
}
}

final def isEmpty: Boolean = stringLiterals.isEmpty
final def nonEmpty: Boolean = stringLiterals.nonEmpty
}

object StringLiteralSequenceV2 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@
package org.knora.webapi.responders.admin

import com.typesafe.scalalogging.LazyLogging
import zio.Task
import zio.URLayer
import zio.ZIO
import zio.ZLayer

import java.util.UUID
import scala.annotation.tailrec

import dsp.errors.*
import dsp.valueobjects.Iri
import dsp.valueobjects.Iri.*
Expand All @@ -26,14 +18,14 @@ import org.knora.webapi.messages.OntologyConstants.Rdfs
import org.knora.webapi.messages.ResponderRequest
import org.knora.webapi.messages.SmartIri
import org.knora.webapi.messages.StringFormatter
import org.knora.webapi.messages.admin.responder.listsmessages.*
import org.knora.webapi.messages.admin.responder.listsmessages.ListNodeCreatePayloadADM.ListChildNodeCreatePayloadADM
import org.knora.webapi.messages.admin.responder.listsmessages.ListNodeCreatePayloadADM.ListRootNodeCreatePayloadADM
import org.knora.webapi.messages.admin.responder.listsmessages.*
import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectADM
import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectGetADM
import org.knora.webapi.messages.admin.responder.projectsmessages.ProjectIdentifierADM.*
import org.knora.webapi.messages.store.triplestoremessages.SparqlExtendedConstructResponse.ConstructPredicateObjects
import org.knora.webapi.messages.store.triplestoremessages.*
import org.knora.webapi.messages.store.triplestoremessages.SparqlExtendedConstructResponse.ConstructPredicateObjects
import org.knora.webapi.messages.twirl.queries.sparql
import org.knora.webapi.responders.IriLocker
import org.knora.webapi.responders.IriService
Expand All @@ -55,6 +47,13 @@ import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Constru
import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Select
import org.knora.webapi.store.triplestore.api.TriplestoreService.Queries.Update
import org.knora.webapi.util.ZioHelper
import zio.Task
import zio.URLayer
import zio.ZIO
import zio.ZLayer

import java.util.UUID
import scala.annotation.tailrec

final case class ListsResponder(
appConfig: AppConfig,
Expand Down Expand Up @@ -83,8 +82,7 @@ final case class ListsResponder(
listCreateRequestADM(createRootNode, apiRequestID)
case ListChildNodeCreateRequestADM(createChildNodeRequest, _, apiRequestID) =>
listChildNodeCreateRequestADM(createChildNodeRequest, apiRequestID)
case ListNodeCommentsDeleteRequestADM(iri, _) => deleteListNodeCommentsADM(iri)
case other => Responder.handleUnexpectedMessage(other, this.getClass.getName)
case other => Responder.handleUnexpectedMessage(other, this.getClass.getName)
}

/**
Expand Down Expand Up @@ -1341,28 +1339,19 @@ final case class ListsResponder(
/**
* Deletes all comments from requested list node (only child).
*/
private def deleteListNodeCommentsADM(nodeIri: IRI): Task[ListNodeCommentsDeleteResponseADM] =
def deleteListNodeCommentsADM(nodeIri: ListIri): Task[ListNodeCommentsDeleteResponseADM] =
for {
node <- listNodeInfoGetADM(nodeIri)

doesNodeHaveComments = node.get.comments.stringLiterals.nonEmpty

_ <- ZIO.when(!doesNodeHaveComments) {
ZIO.fail(BadRequestException(s"Nothing to delete. Node $nodeIri does not have comments."))
}

_ <-
node match {
case Some(_: ListRootNodeInfoADM) => ZIO.fail(BadRequestException("Root node comments cannot be deleted."))
case Some(_: ListChildNodeInfoADM) => ZIO.succeed(false)
case _ => ZIO.fail(InconsistentRepositoryDataException("Bad data. List node expected."))
}

projectIri <- getProjectIriFromNode(nodeIri)
node <- listNodeInfoGetADM(nodeIri.value).someOrFail(NotFoundException(s"Node ${nodeIri.value} not found."))
_ <- ZIO
.fail(BadRequestException("Root node comments cannot be deleted."))
.when(!node.isInstanceOf[ListChildNodeInfoADM])
_ <- ZIO
.fail(BadRequestException(s"Nothing to delete. Node ${nodeIri.value} does not have comments."))
.when(!node.hasComments)
projectIri <- getProjectIriFromNode(nodeIri.value)
namedGraph <- getDataNamedGraph(projectIri)
_ <- triplestore.query(Update(sparql.admin.txt.deleteListNodeComments(namedGraph, nodeIri)))

} yield ListNodeCommentsDeleteResponseADM(nodeIri, commentsDeleted = true)
_ <- triplestore.query(Update(sparql.admin.txt.deleteListNodeComments(namedGraph, nodeIri.value)))
} yield ListNodeCommentsDeleteResponseADM(nodeIri.value, commentsDeleted = true)

/**
* Delete a node (root or child). If a root node is given, check for its usage in data and ontology. If not used,
Expand Down Expand Up @@ -1889,6 +1878,9 @@ object ListsResponder {
): ZIO[ListsResponder, Throwable, ListItemDeleteResponseADM] =
ZIO.serviceWithZIO[ListsResponder](_.deleteListItemRequestADM(iri, user, uuid))

def deleteListNodeCommentsADM(iri: ListIri): ZIO[ListsResponder, Throwable, ListNodeCommentsDeleteResponseADM] =
ZIO.serviceWithZIO[ListsResponder](_.deleteListNodeCommentsADM(iri))

def canDeleteListRequestADM(iri: ListIri): ZIO[ListsResponder, Throwable, CanDeleteListResponseADM] =
ZIO.serviceWithZIO[ListsResponder](_.canDeleteListRequestADM(iri))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,5 @@ final case class ListsRouteADM(
private val routeData: KnoraRouteData,
override protected implicit val runtime: Runtime[routing.Authenticator & StringFormatter & MessageRelay]
) extends KnoraRoute(routeData, runtime) {

private val createNodeRoute: CreateListItemsRouteADM = CreateListItemsRouteADM(routeData, runtime)
private val deleteNodeRoute: DeleteListItemsRouteADM = DeleteListItemsRouteADM(routeData, runtime)

override def makeRoute: Route =
createNodeRoute.makeRoute ~
deleteNodeRoute.makeRoute
override def makeRoute: Route = CreateListItemsRouteADM(routeData, runtime).makeRoute
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,21 @@ case class ListsEndpoints(baseEndpoints: BaseEndpoints) extends ListADMJsonProto
.out(sprayJsonBody[CanDeleteListResponseADM])
.description("Checks if a list can be deleted (none of its nodes is used in data).")

val deleteListsComment = baseEndpoints.securedEndpoint.delete
.in(base / "comments" / listIriPathVar)
.out(sprayJsonBody[ListNodeCommentsDeleteResponseADM])

private val secured =
List(
putListsByIriName,
putListsByIriLabels,
putListsByIriComments,
putListsByIriPosistion,
putListsByIri,
deleteListsByIri
).map(
_.endpoint
)
deleteListsByIri,
deleteListsComment
).map(_.endpoint)

private val public = List(getListsQueryByProjectIriOption, getListsByIri, getListsByIriInfo, getListsCanDeleteByIri)

val endpoints = (secured ++ public).map(_.tag("Admin Lists"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import zio.Random
import zio.Task
import zio.ZIO
import zio.ZLayer

import dsp.errors.BadRequestException
import org.knora.webapi.messages.admin.responder.listsmessages.CanDeleteListResponseADM
import org.knora.webapi.messages.admin.responder.listsmessages.ListItemDeleteResponseADM
import org.knora.webapi.messages.admin.responder.listsmessages.ListNodeCommentsDeleteResponseADM
import org.knora.webapi.messages.admin.responder.listsmessages.NodeInfoGetResponseADM
import org.knora.webapi.messages.admin.responder.listsmessages.NodePositionChangeResponseADM
import org.knora.webapi.responders.admin.ListsResponder
Expand Down Expand Up @@ -75,6 +75,7 @@ final case class ListRestService(
uuid <- Random.nextUUID
response <- listsResponder.deleteListItemRequestADM(iri, user, uuid)
} yield response

}

object ListRestService {
Expand Down Expand Up @@ -164,6 +165,11 @@ final case class ListsEndpointsHandlers(
listsResponder.canDeleteListRequestADM
)

private val deleteListsCommentHandler = SecuredEndpointHandler[ListIri, ListNodeCommentsDeleteResponseADM](
listsEndpoints.deleteListsComment,
_ => listIri => listsResponder.deleteListNodeCommentsADM(listIri)
)

private val public = List(
getListsByIriHandler,
getListsQueryByProjectIriHandler,
Expand All @@ -179,7 +185,8 @@ final case class ListsEndpointsHandlers(
putListsByIriCommentsHandler,
putListsByIriPositionHandler,
putListsByIriHandler,
deleteListsByIriHandler
deleteListsByIriHandler,
deleteListsCommentHandler
).map(mapper.mapSecuredEndpointHandler(_))

val allHandlers = public ++ secured
Expand Down

0 comments on commit 9d9a8a2

Please sign in to comment.