From 6d4594ed0b32654553b32c1660ed5d5f58596b3d Mon Sep 17 00:00:00 2001 From: "Serhii Plyhun (commercial)" Date: Wed, 30 Nov 2022 09:42:09 +0100 Subject: [PATCH] SUP-14472: Two nodes with same path/segment field if binary is filled (#1470) * SUP-14472: Two nodes with same path/segment field if binary is filled * LTS changelog * Unit tests * Warning Co-authored-by: Serhii Plyhun --- LTS-CHANGELOG.adoc | 5 + .../node/BinaryUploadHandlerImpl.java | 2 + .../core/data/dao/PersistingContentDao.java | 3 +- .../node/NodeWebRootConflictEndpointTest.java | 126 +++++++++++++++++- 4 files changed, 133 insertions(+), 3 deletions(-) diff --git a/LTS-CHANGELOG.adoc b/LTS-CHANGELOG.adoc index 3ace40a64d..a9c066688f 100644 --- a/LTS-CHANGELOG.adoc +++ b/LTS-CHANGELOG.adoc @@ -17,6 +17,11 @@ include::content/docs/variables.adoc-include[] The LTS changelog lists releases which are only accessible via a commercial subscription. All fixes and changes in LTS releases will be released the next minor release. Changes from LTS 1.4.x will be included in release 1.5.0. +[[v1.8.15]] +== 1.8.15 (TBD) + +icon:check[] Core: Having a binary non-segment field update might break the uniqueness of the segment field value, allowing creation of multiple nodes with the same segment/webroot value. This has now been fixed. + [[v1.8.14]] == 1.8.14 (22.11.2022) diff --git a/core/src/main/java/com/gentics/mesh/core/endpoint/node/BinaryUploadHandlerImpl.java b/core/src/main/java/com/gentics/mesh/core/endpoint/node/BinaryUploadHandlerImpl.java index 525cbdfecc..1ab4a12c47 100644 --- a/core/src/main/java/com/gentics/mesh/core/endpoint/node/BinaryUploadHandlerImpl.java +++ b/core/src/main/java/com/gentics/mesh/core/endpoint/node/BinaryUploadHandlerImpl.java @@ -372,6 +372,8 @@ private Single storeUploadInGraph(InternalActionContext ac, List client().publishNode(PROJECT_NAME, otherNodeUuid), CONFLICT, "node_conflicting_segmentfield_publish", "slug", conflictingName); } + + @Test + public void testBinaryNonSegmentFieldBreaksUniquenessNodeApi() { + SchemaResponse binContentSchema = tx(tx -> { + SchemaCreateRequest request = new SchemaCreateRequest(); + request.setName("schema_" + System.currentTimeMillis()); + request.setContainer(false); + request.setSegmentField("name"); + + StringFieldSchema nameFieldSchema = new StringFieldSchemaImpl(); + nameFieldSchema.setName("name"); + nameFieldSchema.setLabel("Name"); + request.addField(nameFieldSchema); + + BinaryFieldSchema binaryFieldSchema = new BinaryFieldSchemaImpl(); + binaryFieldSchema.setName("binary"); + binaryFieldSchema.setLabel("Binary Data"); + request.addField(binaryFieldSchema); + + SchemaResponse schema = call(() -> client().createSchema(request)); + + call(() -> client().assignSchemaToProject(PROJECT_NAME, schema.getUuid())); + + return schema; + }); + + tx(() -> { + // create the initial content + NodeCreateRequest create = new NodeCreateRequest(); + create.setParentNodeUuid(folderUuid()); + create.setLanguage("en"); + create.setSchema(new SchemaReferenceImpl().setName(binContentSchema.getName()).setUuid(binContentSchema.getUuid())); + create.getFields().put("name", FieldUtil.createStringField("title_12345")); + NodeResponse node1 = client().createNode(project().getName(), create).toSingle().blockingGet(); + + // create the illegal content - node cannot appear with already used segment value + NodeCreateRequest illegalCreate = new NodeCreateRequest(); + illegalCreate.setParentNodeUuid(folderUuid()); + illegalCreate.setLanguage("en"); + illegalCreate.setSchema(new SchemaReferenceImpl().setName(binContentSchema.getName()).setUuid(binContentSchema.getUuid())); + illegalCreate.getFields().put("name", FieldUtil.createStringField("title_12345")); + call(() -> client().createNode(PROJECT_NAME, illegalCreate), CONFLICT, "node_conflicting_segmentfield_update", "name", "title_12345"); + + // update binary field + Buffer buffer = getBuffer("/pictures/android-gps.jpg"); + call(() -> client().updateNodeBinaryField(PROJECT_NAME, node1.getUuid(), "en", "0.1", "binary", new ByteArrayInputStream(buffer.getBytes()), buffer.length(), "test.jpg", "image/jpeg")); + + // check the node still cannot appear with the same segment value + call(() -> client().createNode(PROJECT_NAME, illegalCreate), CONFLICT, "node_conflicting_segmentfield_update", "name", "title_12345"); + + // cleanup + call(() -> client().deleteNode(PROJECT_NAME, node1.getUuid())); + call(() -> client().unassignSchemaFromProject(PROJECT_NAME, binContentSchema.getUuid())); + call(() -> client().deleteSchema(binContentSchema.getUuid())); + }); + } + + + @Test + public void testBinaryNonSegmentFieldBreaksUniquenessWebrootApi() { + SchemaResponse binContentSchema = tx(tx -> { + SchemaCreateRequest request = new SchemaCreateRequest(); + request.setName("schema_" + System.currentTimeMillis()); + request.setContainer(false); + request.setSegmentField("name"); + + StringFieldSchema nameFieldSchema = new StringFieldSchemaImpl(); + nameFieldSchema.setName("name"); + nameFieldSchema.setLabel("Name"); + request.addField(nameFieldSchema); + + BinaryFieldSchema binaryFieldSchema = new BinaryFieldSchemaImpl(); + binaryFieldSchema.setName("binary"); + binaryFieldSchema.setLabel("Binary Data"); + request.addField(binaryFieldSchema); + + SchemaResponse schema = call(() -> client().createSchema(request)); + + call(() -> client().assignSchemaToProject(PROJECT_NAME, schema.getUuid())); + + return schema; + }); + + tx(() -> { + // create the initial content + NodeCreateRequest create = new NodeCreateRequest(); + create.setParentNodeUuid(folderUuid()); + create.setLanguage("en"); + create.setSchema(new SchemaReferenceImpl().setName(binContentSchema.getName()).setUuid(binContentSchema.getUuid())); + create.getFields().put("name", FieldUtil.createStringField("title_12345")); + NodeResponse node1 = client().webrootCreate(PROJECT_NAME, "/title_12345", create).toSingle().blockingGet(); + + // create the illegal content - node cannot appear with already used segment value + NodeCreateRequest illegalCreate = new NodeCreateRequest(); + illegalCreate.setParentNodeUuid(folderUuid()); + illegalCreate.setLanguage("en"); + illegalCreate.setSchema(new SchemaReferenceImpl().setName(binContentSchema.getName()).setUuid(binContentSchema.getUuid())); + illegalCreate.getFields().put("name", FieldUtil.createStringField("title_12345")); + call(() -> client().webrootCreate(PROJECT_NAME, "/title_12345", illegalCreate), CONFLICT, "node_conflicting_segmentfield_update", "name", "title_12345"); + + // update binary field + Buffer buffer = getBuffer("/pictures/android-gps.jpg"); + call(() -> client().updateNodeBinaryField(PROJECT_NAME, node1.getUuid(), "en", "0.1", "binary", new ByteArrayInputStream(buffer.getBytes()), buffer.length(), "test.jpg", "image/jpeg")); + + // check the node still cannot appear with the same segment value + call(() -> client().webrootCreate(PROJECT_NAME, "/title_12345", illegalCreate), CONFLICT, "node_conflicting_segmentfield_update", "name", "title_12345"); + + // cleanup + call(() -> client().deleteNode(PROJECT_NAME, node1.getUuid())); + call(() -> client().unassignSchemaFromProject(PROJECT_NAME, binContentSchema.getUuid())); + call(() -> client().deleteSchema(binContentSchema.getUuid())); + }); + } }