From 6c2e9036dbaf2b00a6492273c5e4c2d23043cc36 Mon Sep 17 00:00:00 2001 From: Sepideh Alassi Date: Fri, 9 Oct 2020 20:50:47 +0200 Subject: [PATCH] DSP-740 Update List Name (#1727) * feature (updateListName) listName can be changed * fix (updateListName) add check for uniqueness of the names and fix the failing test * refactor (updateListName) remove the redundant route * feature (updateList) make comments and labels in payload of update request optional * refactor (updateList) clear error message for empty labels or comments in payload * feature (updateListName) add test data for updating list name * refactor (updateListName) checks for empty optional labels and comments * docs (updateListName) fix generate test data documentation * feature (updateListName) update `expected-client-test-data.txt` --- docs/03-apis/api-admin/lists.md | 18 ++++++- .../generating-client-test-data.md | 4 +- webapi/scripts/expected-client-test-data.txt | 2 + .../listsmessages/ListsMessagesADM.scala | 15 ++++-- .../listsmessages/ListsMessagesUtilADM.scala | 2 +- .../responders/admin/ListsResponderADM.scala | 29 +++++++--- .../webapi/routing/admin/ListsRouteADM.scala | 30 +---------- .../sparql/admin/updateListInfo.scala.txt | 22 ++++++-- .../webapi/e2e/admin/ListsADME2ESpec.scala | 54 ++++++++++++++++--- .../listsmessages/ListsMessagesADMSpec.scala | 9 ++-- .../admin/ListsResponderADMSpec.scala | 33 ++++++++---- 11 files changed, 146 insertions(+), 72 deletions(-) diff --git a/docs/03-apis/api-admin/lists.md b/docs/03-apis/api-admin/lists.md index bbc77902c9..7f0bbc8547 100644 --- a/docs/03-apis/api-admin/lists.md +++ b/docs/03-apis/api-admin/lists.md @@ -26,10 +26,10 @@ License along with Knora. If not, see . - `GET: /admin/lists[?projectIri=]` : return all lists optionally filtered by project - `GET: /admin/lists/` : return complete list with children - `POST: /admin/lists` : create new list +- `PUT: /admin/lists/` : update list information - `POST: /admin/lists/` : create new child node under the supplied parent node IRI - NOT IMPLEMENTED: `DELETE: /admin/lists/` : delete list including children if not used - `GET: /admin/lists/infos/` : return list information (without children) -- `PUT: /admin/lists/infos/` : update list information **List Node operations** @@ -103,21 +103,35 @@ Additionally, each list can have an optional custom IRI (of [Knora IRI](../api-v - GET: `/admin/lists/infos/` ### Update list's information +The basic information of a list such as its labels, comments, name, or all of them can be updated. The parameters that +must be updated together with the new value must be given in the JSON body of the request together with the IRI of the +list and the IRI of the project it belongs to. - Required permission: none - Update list information - - PUT: `/admin/lists/infos/` + - PUT: `/admin/lists/` - BODY: ```json { "listIri": "listIri", "projectIri": "someprojectiri", + "name": "a new name", "labels": [{ "value": "Neue geönderte Liste", "language": "de"}, { "value": "Changed list", "language": "en"}], "comments": [{ "value": "Neuer Kommentar", "language": "de"}, { "value": "New comment", "language": "en"}] } ``` +If only name of the list must be updated, it can be given as below in the body of the request: + +```json + { + "listIri": "listIri", + "projectIri": "someprojectiri", + "name": "another name" + } +``` + ## List Node Operations ### Get List Node Information diff --git a/docs/05-internals/development/generating-client-test-data.md b/docs/05-internals/development/generating-client-test-data.md index 276c29ccf7..207604cba5 100644 --- a/docs/05-internals/development/generating-client-test-data.md +++ b/docs/05-internals/development/generating-client-test-data.md @@ -39,13 +39,13 @@ with the list in `webapi/scripts/expected-client-test-data.txt`. To generate client test data, type: ``` -make test-e2e +make client-test-data ``` When the tests have finished running, you will find the file `client-test-data.zip` in the current directory. -If generated client test data changes, run `make test-e2e`, then run +If generated client test data changes, run `make client-test-data`, then run this script to update the list of expected test data files: ``` diff --git a/webapi/scripts/expected-client-test-data.txt b/webapi/scripts/expected-client-test-data.txt index c119b11763..675ef66710 100644 --- a/webapi/scripts/expected-client-test-data.txt +++ b/webapi/scripts/expected-client-test-data.txt @@ -32,6 +32,8 @@ test-data/admin/lists/update-list-info-comment-label-multiple-languages-request. test-data/admin/lists/update-list-info-comment-label-multiple-languages-response.json test-data/admin/lists/update-list-info-request.json test-data/admin/lists/update-list-info-response.json +test-data/admin/lists/update-list-name-request.json +test-data/admin/lists/update-list-name-response.json test-data/admin/permissions/ test-data/admin/permissions/create-administrative-permission-request.json test-data/admin/permissions/create-administrative-permission-response.json diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala index 5b923adc32..1f159d3af9 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADM.scala @@ -129,8 +129,9 @@ case class CreateChildNodeApiRequestADM(parentNodeIri: IRI, */ case class ChangeListInfoApiRequestADM(listIri: IRI, projectIri: IRI, - labels: Seq[StringLiteralV2], - comments: Seq[StringLiteralV2]) extends ListADMJsonProtocol { + name: Option[String] = None, + labels: Option[Seq[StringLiteralV2]] = None, + comments: Option[Seq[StringLiteralV2]] = None) extends ListADMJsonProtocol { private val stringFormatter = StringFormatter.getInstanceForConstantOntologies @@ -150,10 +151,14 @@ case class ChangeListInfoApiRequestADM(listIri: IRI, throw BadRequestException(PROJECT_IRI_INVALID_ERROR) } - if (labels.isEmpty && comments.isEmpty) { - throw BadRequestException(REQUEST_NOT_CHANGING_DATA_ERROR) + // If payload containes label or comments they should not be empty + if (labels.exists(_.isEmpty)) { + throw BadRequestException(UPDATE_REQUEST_EMPTY_LABEL_OR_COMMENT_ERROR) } + if (comments.exists(_.isEmpty)) { + throw BadRequestException(UPDATE_REQUEST_EMPTY_LABEL_OR_COMMENT_ERROR) + } def toJsValue: JsValue = changeListInfoApiRequestADMFormat.write(this) } @@ -963,7 +968,7 @@ trait ListADMJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol with implicit val createListApiRequestADMFormat: RootJsonFormat[CreateListApiRequestADM] = jsonFormat(CreateListApiRequestADM, "id", "projectIri", "name", "labels", "comments") implicit val createListNodeApiRequestADMFormat: RootJsonFormat[CreateChildNodeApiRequestADM] = jsonFormat(CreateChildNodeApiRequestADM, "parentNodeIri", "projectIri", "name", "labels", "comments") - implicit val changeListInfoApiRequestADMFormat: RootJsonFormat[ChangeListInfoApiRequestADM] = jsonFormat(ChangeListInfoApiRequestADM, "listIri", "projectIri", "labels", "comments") + implicit val changeListInfoApiRequestADMFormat: RootJsonFormat[ChangeListInfoApiRequestADM] = jsonFormat(ChangeListInfoApiRequestADM, "listIri", "projectIri", "name", "labels", "comments") implicit val nodePathGetResponseADMFormat: RootJsonFormat[NodePathGetResponseADM] = jsonFormat(NodePathGetResponseADM, "elements") implicit val listsGetResponseADMFormat: RootJsonFormat[ListsGetResponseADM] = jsonFormat(ListsGetResponseADM, "lists") implicit val listGetResponseADMFormat: RootJsonFormat[ListGetResponseADM] = jsonFormat(ListGetResponseADM, "list") diff --git a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala index af8c229e7d..e1b7d82c84 100644 --- a/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesUtilADM.scala @@ -29,5 +29,5 @@ object ListsMessagesUtilADM { val LABEL_MISSING_ERROR = "At least one label needs to be supplied." val LIST_CREATE_PERMISSION_ERROR = "A list can only be created by the project or system administrator." val LIST_CHANGE_PERMISSION_ERROR = "A list can only be changed by the project or system administrator." - val REQUEST_NOT_CHANGING_DATA_ERROR = "No data would be changed." + val UPDATE_REQUEST_EMPTY_LABEL_OR_COMMENT_ERROR = "List labels and comments cannot be empty." } diff --git a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala index ce3802d1b9..f0b0500bc0 100644 --- a/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/responders/admin/ListsResponderADM.scala @@ -675,18 +675,17 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde * The actual task run with an IRI lock. */ def listInfoChangeTask(listIri: IRI, changeListRequest: ChangeListInfoApiRequestADM, requestingUser: UserADM, apiRequestID: UUID): Future[ListInfoGetResponseADM] = for { - // check if required information is supplied - _ <- Future(if (changeListRequest.labels.isEmpty && changeListRequest.comments.isEmpty) throw BadRequestException(REQUEST_NOT_CHANGING_DATA_ERROR)) - _ = if (!listIri.equals(changeListRequest.listIri)) throw BadRequestException("List IRI in path and payload don't match.") + // check if listIRI in path and payload match + _ <- Future( + if (!listIri.equals(changeListRequest.listIri)) throw BadRequestException("List IRI in path and payload don't match.") + ) // check if the requesting user is allowed to perform operation - _ <- Future( - if (!requestingUser.permissions.isProjectAdmin(changeListRequest.projectIri) && !requestingUser.permissions.isSystemAdmin) { + _ = if (!requestingUser.permissions.isProjectAdmin(changeListRequest.projectIri) && !requestingUser.permissions.isSystemAdmin) { // not project or a system admin // log.debug("same user: {}, system admin: {}", userProfile.userData.user_id.contains(userIri), userProfile.permissionData.isSystemAdmin) throw ForbiddenException(LIST_CHANGE_PERMISSION_ERROR) } - ) /* Verify that the list exists. */ maybeList <- listGetADM(rootNodeIri = listIri, requestingUser = KnoraSystemInstances.Users.SystemUser) @@ -702,6 +701,14 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde case None => throw BadRequestException(s"Project '${list.listinfo.projectIri}' not found.") } + /* verify that the list name is unique for the project */ + nodeNameUnique: Boolean <- listNodeNameIsProjectUnique(changeListRequest.projectIri, changeListRequest.name) + _ = if (!nodeNameUnique) { + throw DuplicateValueException(s"The name ${changeListRequest.name.get} is already used by a list inside the project ${changeListRequest.projectIri}.") + } + + hasOldName: Boolean = list.listinfo.name.nonEmpty + // get the data graph of the project. dataNamedGraph = stringFormatter.projectDataNamedGraphV2(project) @@ -710,6 +717,8 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde dataNamedGraph = dataNamedGraph, triplestore = settings.triplestoreType, listIri = listIri, + hasOldName = hasOldName, + maybeName = changeListRequest.name, projectIri = project.id, listClassIri = OntologyConstants.KnoraBase.ListNode, maybeLabels = changeListRequest.labels, @@ -725,15 +734,19 @@ class ListsResponderADM(responderData: ResponderData) extends Responder(responde _ = if (changeListRequest.labels.nonEmpty) { - if (updatedList.listinfo.labels.stringLiterals.diff(changeListRequest.labels).nonEmpty) throw UpdateNotPerformedException("Lists's 'labels' where not updated. Please report this as a possible bug.") + if (updatedList.listinfo.labels.stringLiterals.diff(changeListRequest.labels.get).nonEmpty) throw UpdateNotPerformedException("Lists's 'labels' where not updated. Please report this as a possible bug.") } _ = if (changeListRequest.comments.nonEmpty) { - if (updatedList.listinfo.comments.stringLiterals.diff(changeListRequest.comments).nonEmpty) + if (updatedList.listinfo.comments.stringLiterals.diff(changeListRequest.comments.get).nonEmpty) throw UpdateNotPerformedException("List's 'comments' was not updated. Please report this as a possible bug.") } + _ = if (changeListRequest.name.nonEmpty) { + if (updatedList.listinfo.name.get != changeListRequest.name.get) + throw UpdateNotPerformedException("List's 'name' was not updated. Please report this as a possible bug.") + } // _ = log.debug(s"listInfoChangeRequest - updatedList: {}", updatedList) } yield ListInfoGetResponseADM(listinfo = updatedList.listinfo) diff --git a/webapi/src/main/scala/org/knora/webapi/routing/admin/ListsRouteADM.scala b/webapi/src/main/scala/org/knora/webapi/routing/admin/ListsRouteADM.scala index 3b43b7cb2c..e1901995f0 100644 --- a/webapi/src/main/scala/org/knora/webapi/routing/admin/ListsRouteADM.scala +++ b/webapi/src/main/scala/org/knora/webapi/routing/admin/ListsRouteADM.scala @@ -48,8 +48,9 @@ class ListsRouteADM(routeData: KnoraRouteData) extends KnoraRoute(routeData) wit /** * Returns the route. */ + override def knoraApiPath: Route = getLists ~ createList ~ getList ~ updateList ~ createListChildNode ~ deleteListNode ~ - getListInfo ~ updateListInfo ~ getListNodeInfo + getListInfo ~ getListNodeInfo /* return all lists optionally filtered by project */ @ApiOperation(value = "Get lists", nickname = "getlists", httpMethod = "GET", response = classOf[ListsGetResponseADM]) @@ -245,33 +246,6 @@ class ListsRouteADM(routeData: KnoraRouteData) extends KnoraRoute(routeData) wit } } - def updateListInfo: Route = path(ListsBasePath / "infos" / Segment) { iri => - put { - /* update list info */ - entity(as[ChangeListInfoApiRequestADM]) { apiRequest => - requestContext => - val listIri = stringFormatter.validateAndEscapeIri(iri, throw BadRequestException(s"Invalid param list IRI: $iri")) - - val requestMessage: Future[ListInfoChangeRequestADM] = for { - requestingUser <- getUserADM(requestContext) - } yield ListInfoChangeRequestADM( - listIri = listIri, - changeListRequest = apiRequest, - requestingUser = requestingUser, - apiRequestID = UUID.randomUUID() - ) - - RouteUtilADM.runJsonRoute( - requestMessage, - requestContext, - settings, - responderManager, - log - ) - } - } - } - def getListNodeInfo: Route = path(ListsBasePath / "nodes" / Segment) { iri => get { /* return information about a single node (without children) */ diff --git a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/updateListInfo.scala.txt b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/updateListInfo.scala.txt index e92d9ed4dc..395b3473b9 100644 --- a/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/updateListInfo.scala.txt +++ b/webapi/src/main/twirl/org/knora/webapi/messages/twirl/queries/sparql/admin/updateListInfo.scala.txt @@ -29,6 +29,8 @@ * @param listIri the IRI of the list we want to update. * @param projectIri the IRI of the list's project. * @param listClassIri the IRI of the OWL class that the list should belong to. + * @param hasOldName the old name of the list. + * @param maybeName the new name of the list. * @param maybelabels the new optional label values. * @param maybeComments the new optional comment values. *@ @@ -37,8 +39,10 @@ listIri: IRI, projectIri: IRI, listClassIri: IRI, - maybeLabels: Seq[StringLiteralV2], - maybeComments: Seq[StringLiteralV2]) + hasOldName: Boolean, + maybeName : Option[String], + maybeLabels: Option[Seq[StringLiteralV2]], + maybeComments: Option[Seq[StringLiteralV2]]) PREFIX rdf: PREFIX rdfs: @@ -54,6 +58,10 @@ DELETE { ?listIri rdfs:label ?currentLabels . } + @if(hasOldName && maybeName.nonEmpty) { + ?listIri knora-base:listNodeName ?currentListName . + } + @if(maybeComments.nonEmpty) { ?listIri rdfs:comment ?currentComments . } @@ -62,8 +70,12 @@ DELETE { @* Add the new values. *@ + @if(maybeName.nonEmpty) { + ?listIri knora-base:listNodeName "@maybeName.get"^^xsd:string . + } + @if(maybeLabels.nonEmpty) { - @for(label <- maybeLabels) { + @for(label <- maybeLabels.get) { @if(label.language.nonEmpty) { ?listIri rdfs:label """@label.value"""@@@{label.language.get} . } else { @@ -73,7 +85,7 @@ DELETE { } @if(maybeComments.nonEmpty) { - @for(comment <- maybeComments) { + @for(comment <- maybeComments.get) { @if(comment.language.nonEmpty) { ?listIri rdfs:comment """@comment.value"""@@@{comment.language.get} . } else { @@ -109,6 +121,8 @@ WHERE { ?listIri knora-base:attachedToProject ?projectIri . + optional {?listIri knora-base:listNodeName ?currentListName .} + optional {?listIri rdfs:label ?currentLabels .} optional {?listIri rdfs:comment ?currentComments .} diff --git a/webapi/src/test/scala/org/knora/webapi/e2e/admin/ListsADME2ESpec.scala b/webapi/src/test/scala/org/knora/webapi/e2e/admin/ListsADME2ESpec.scala index 6b3593dde1..294c9e3d00 100644 --- a/webapi/src/test/scala/org/knora/webapi/e2e/admin/ListsADME2ESpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/e2e/admin/ListsADME2ESpec.scala @@ -469,7 +469,7 @@ class ListsADME2ESpec extends E2ESpec(ListsADME2ESpec.config) with SessionJsonPr ) val encodedListUrl = java.net.URLEncoder.encode(newListIri.get, "utf-8") - val request = Put(baseApiUrl + s"/admin/lists/infos/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, updateListInfo)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) + val request = Put(baseApiUrl + s"/admin/lists/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, updateListInfo)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) val response: HttpResponse = singleAwaitingRequest(request) // log.debug(s"response: ${response.toString}") response.status should be(StatusCodes.OK) @@ -496,6 +496,48 @@ class ListsADME2ESpec extends E2ESpec(ListsADME2ESpec.config) with SessionJsonPr ) } + "update basic list information with a new name" in { + val updateListName = + s"""{ + | "listIri": "${newListIri.get}", + | "projectIri": "${SharedTestDataADM.ANYTHING_PROJECT_IRI}", + | "name": "a totally new name" + |}""".stripMargin + clientTestDataCollector.addFile( + TestDataFileContent( + filePath = TestDataFilePath( + directoryPath = clientTestDataPath, + filename = "update-list-name-request", + fileExtension = "json" + ), + text = updateListName + ) + ) + val encodedListUrl = java.net.URLEncoder.encode(newListIri.get, "utf-8") + + val request = Put(baseApiUrl + s"/admin/lists/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, updateListName)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) + val response: HttpResponse = singleAwaitingRequest(request) + // log.debug(s"response: ${response.toString}") + response.status should be(StatusCodes.OK) + + val receivedListInfo: ListRootNodeInfoADM = AkkaHttpUtils.httpResponseToJson(response).fields("listinfo").convertTo[ListRootNodeInfoADM] + + receivedListInfo.projectIri should be (SharedTestDataADM.ANYTHING_PROJECT_IRI) + + receivedListInfo.name should be (Some("a totally new name")) + + clientTestDataCollector.addFile( + TestDataFileContent( + filePath = TestDataFilePath( + directoryPath = clientTestDataPath, + filename = "update-list-name-response", + fileExtension = "json" + ), + text = responseToString(response) + ) + ) + } + "update basic list information with repeated comment and label in different languages" in { val updateListInfoWithRepeatedCommentAndLabelValuesRequest: String = @@ -527,7 +569,7 @@ class ListsADME2ESpec extends E2ESpec(ListsADME2ESpec.config) with SessionJsonPr val encodedListUrl = java.net.URLEncoder.encode("http://rdfh.ch/lists/0001/treeList", "utf-8") - val request = Put(baseApiUrl + s"/admin/lists/infos/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, updateListInfoWithRepeatedCommentAndLabelValuesRequest)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) + val request = Put(baseApiUrl + s"/admin/lists/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, updateListInfoWithRepeatedCommentAndLabelValuesRequest)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) val response: HttpResponse = singleAwaitingRequest(request) // log.debug(s"response: ${response.toString}") response.status should be(StatusCodes.OK) @@ -567,7 +609,7 @@ class ListsADME2ESpec extends E2ESpec(ListsADME2ESpec.config) with SessionJsonPr val encodedListUrl = java.net.URLEncoder.encode(newListIri.get, "utf-8") - val request = Put(baseApiUrl + s"/admin/lists/infos/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, params)) ~> addCredentials(anythingUserCreds.basicHttpCredentials) + val request = Put(baseApiUrl + s"/admin/lists/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, params)) ~> addCredentials(anythingUserCreds.basicHttpCredentials) val response: HttpResponse = singleAwaitingRequest(request) // log.debug(s"response: ${response.toString}") response.status should be(StatusCodes.Forbidden) @@ -588,7 +630,7 @@ class ListsADME2ESpec extends E2ESpec(ListsADME2ESpec.config) with SessionJsonPr |} """.stripMargin - val request01 = Put(baseApiUrl + s"/admin/lists/infos/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, params01)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) + val request01 = Put(baseApiUrl + s"/admin/lists/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, params01)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) val response01: HttpResponse = singleAwaitingRequest(request01) // log.debug(s"response: ${response.toString}") response01.status should be(StatusCodes.BadRequest) @@ -604,7 +646,7 @@ class ListsADME2ESpec extends E2ESpec(ListsADME2ESpec.config) with SessionJsonPr |} """.stripMargin - val request02 = Put(baseApiUrl + s"/admin/lists/infos/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, params02)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) + val request02 = Put(baseApiUrl + s"/admin/lists/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, params02)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) val response02: HttpResponse = singleAwaitingRequest(request02) // log.debug(s"response: ${response.toString}") response02.status should be(StatusCodes.BadRequest) @@ -620,7 +662,7 @@ class ListsADME2ESpec extends E2ESpec(ListsADME2ESpec.config) with SessionJsonPr |} """.stripMargin - val request03 = Put(baseApiUrl + s"/admin/lists/infos/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, params03)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) + val request03 = Put(baseApiUrl + s"/admin/lists/" + encodedListUrl, HttpEntity(ContentTypes.`application/json`, params03)) ~> addCredentials(anythingAdminUserCreds.basicHttpCredentials) val response03: HttpResponse = singleAwaitingRequest(request03) // log.debug(s"response: ${response.toString}") response03.status should be(StatusCodes.BadRequest) diff --git a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala index 0903182c24..c2b6d63f79 100644 --- a/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/messages/admin/responder/listsmessages/ListsMessagesADMSpec.scala @@ -220,8 +220,7 @@ class ListsMessagesADMSpec extends AnyWordSpecLike with Matchers with ListADMJso |{ | "listIri": "$exampleListIri", | "projectIri": "", - | "labels": [{ "value": "Neue geönderte Liste", "language": "de"}, { "value": "Changed list", "language": "en"}], - | "comments": [{ "value": "Neuer Kommentar", "language": "de"}, { "value": "New comment", "language": "en"}] + | "labels": [{ "value": "Neue geönderte Liste", "language": "de"}, { "value": "Changed list", "language": "en"}] |} """.stripMargin @@ -237,8 +236,7 @@ class ListsMessagesADMSpec extends AnyWordSpecLike with Matchers with ListADMJso |{ | "listIri": "$exampleListIri", | "projectIri": "notvalidIRI", - | "labels": [{ "value": "Neue geönderte Liste", "language": "de"}, { "value": "Changed list", "language": "en"}], - | "comments": [{ "value": "Neuer Kommentar", "language": "de"}, { "value": "New comment", "language": "en"}] + | "name": "a new name" |} """.stripMargin @@ -261,8 +259,7 @@ class ListsMessagesADMSpec extends AnyWordSpecLike with Matchers with ListADMJso val thrown = the [BadRequestException] thrownBy payload.parseJson.convertTo[ChangeListInfoApiRequestADM] - thrown.getMessage should equal (REQUEST_NOT_CHANGING_DATA_ERROR) - + thrown.getMessage should equal (UPDATE_REQUEST_EMPTY_LABEL_OR_COMMENT_ERROR) } "throw 'BadRequestException' for `CreateChildNodeApiRequestADM` when list node iri is empty" in { diff --git a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala index f7f1892e20..2a1b41447a 100644 --- a/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala +++ b/webapi/src/test/scala/org/knora/webapi/responders/admin/ListsResponderADMSpec.scala @@ -26,7 +26,7 @@ import akka.testkit._ import com.typesafe.config.{Config, ConfigFactory} import org.knora.webapi.sharedtestdata.SharedTestDataV1._ import org.knora.webapi._ -import org.knora.webapi.exceptions.ForbiddenException +import org.knora.webapi.exceptions.{DuplicateValueException, ForbiddenException} import org.knora.webapi.messages.admin.responder.listsmessages.ListsMessagesUtilADM._ import org.knora.webapi.messages.admin.responder.listsmessages._ import org.knora.webapi.messages.store.triplestoremessages.{RdfDataObject, StringLiteralV2} @@ -222,15 +222,16 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with changeListRequest = ChangeListInfoApiRequestADM( listIri = newListIri.get, projectIri = IMAGES_PROJECT_IRI, - labels = Seq( + name = Some("updated name"), + labels = Some(Seq( StringLiteralV2(value = "Neue geänderte Liste", language = Some("de")), StringLiteralV2(value = "Changed list", language = Some("en")) - ), - comments = Seq( + )), + comments = Some(Seq( StringLiteralV2(value = "Neuer Kommentar", language = Some("de")), StringLiteralV2(value = "New comment", language = Some("en")) ) - ), + )), requestingUser = SharedTestDataADM.imagesUser01, apiRequestID = UUID.randomUUID ) @@ -239,7 +240,7 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with val listInfo = received.listinfo listInfo.projectIri should be (IMAGES_PROJECT_IRI) - + listInfo.name should be (Some("updated name")) val labels: Seq[StringLiteralV2] = listInfo.labels.stringLiterals labels.size should be (2) labels.sorted should be (Seq( @@ -253,7 +254,19 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with StringLiteralV2(value = "Neuer Kommentar", language = Some("de")), StringLiteralV2(value = "New comment", language = Some("en")) ).sorted) + } + "not update basic list information if name is duplicate" in { + responderManager ! ListInfoChangeRequestADM( + listIri = newListIri.get, + changeListRequest = ChangeListInfoApiRequestADM( + listIri = newListIri.get, + projectIri = IMAGES_PROJECT_IRI, + name = Some("sommer")), + requestingUser = SharedTestDataADM.imagesUser01, + apiRequestID = UUID.randomUUID + ) + expectMsg(Failure(DuplicateValueException("The name sommer is already used by a list inside the project http://rdfh.ch/projects/00FF."))) } "return a 'ForbiddenException' if the user changing the list is not project or system admin" in { @@ -262,15 +275,15 @@ class ListsResponderADMSpec extends CoreSpec(ListsResponderADMSpec.config) with changeListRequest = ChangeListInfoApiRequestADM( listIri = newListIri.get, projectIri = IMAGES_PROJECT_IRI, - labels = Seq( + labels = Some(Seq( StringLiteralV2(value = "Neue geänderte Liste", language = Some("de")), StringLiteralV2(value = "Changed list", language = Some("en")) - ), - comments = Seq( + )), + comments = Some(Seq( StringLiteralV2(value = "Neuer Kommentar", language = Some("de")), StringLiteralV2(value = "New comment", language = Some("en")) ) - ), + )), requestingUser = SharedTestDataADM.imagesUser02, apiRequestID = UUID.randomUUID )