Fonto Why & How: Why is my operation on a locked document enabled?!

In this weekly series, Martin describes a question that was raised by a Fonto developer, how it was resolved and why Fonto behaved like that in the first place. This week, a partner sees enabled operations for a document they have no rights to edit!

A support question came in: an author loaded a document that was locked by someone else. They right-licked on an image and saw they could replace the image: the operation was enabled. When they did it though, and went through the modal, the replacement was not actually processed. Nothing terrible went wrong and no documents were harmed, but it was still confusing. The partner got this on their plate and they sent us a support ticket.

The operation was straight-forward: a modal opens, accepts the initially selected image and uses the set-attributes operation to write the new selectedImageId back. We reproduced it on our own editor and we were hit by the first difficulty: locking the document.

The fonto development tools are no replacement for an actual CMS. For instance, locking is not done like a CMS would do it. Running fdt with the -lL flag (that’s a lower l and an upper L), all the documents are loaded with the lock neither available or acquired.

The operation looked like this:

{
	"contextual-edit-graphic": {
		"label": "t__Change graphic…",
		"description": "t__Refer to a different graphic.",
		"icon": "pencil",
		"steps": [
			{
				"type": "operation/:_open-image-modal-for-edit",
				"data": {
					"selectedImageId": "x__$data?contextNode/@xlink:href"
				}
			},
			{
				"type": "operation/set-attributes",
				"data": {
					"contextNodeId": "{{contextNodeId}}",
					"attributes": {
						"xlink:href": "{{selectedImageId}}"
					}
				}
			}
		]
	}
}

This operation does the following:

  1. Set the selectedImageId stepdata property to whatever the current href value is.
  2. Open an image modal; the selectedImageId is picked up there to select the current image.
  3. Set the href attribute to whatever the user selected in the modal

When Fonto is computing state for the operation, it will of course not open a modal: we cannot predict what a user will do, so the modal will just never open. Instead, it will skip the step. Skipping the step will not change the stepdata. Because it is not changed, the set-attributes will not do anything. Not changing anything can happen on any document, even those that are not editable.

The fix for this is to make sure the operation works differently when running it during the getState flow:

{
	"contextual-edit-graphic": {
		"label": "t__Change graphic…",
		"description": "t__Refer to a different graphic.",
		"icon": "pencil",
		"getStateSteps": [
			{
				"type": "operation/set-attributes",
				"data": {
					"contextNodeId": "{{contextNodeId}}",
					"attributes": {
						"xlink:href": "dummy-value"
					}
				}
			}
		],
		"steps": [
			{
				"type": "operation/:_open-image-modal-for-edit",
				"data": {
					"selectedImageId": "x__$data?contextNode/@xlink:href"
				}
			},
			{
				"type": "operation/set-attributes",
				"data": {
					"contextNodeId": "{{contextNodeId}}",
					"attributes": {
						"xlink:href": "{{selectedImageId}}"
					}
				}
			}
		]
	}
}	

But why?

This whole flow may not make sense when reading it the first time: why do we not disable any operations on locked documents? The reason is twofold:

We may not always know an edit is targeted at a document that is locked. Some editors load multiple documents at once. For some operations (like opening a sidebar), we do not care if the document is locked: that’s just possible.

But why do we do not disable an operation if we do know it targets a locked document? That should be possible right? Just read from the contextNodeId property! That’s also not always enough: there are some operations that are targeted to a document that are available if a document is locked. For example the set-selection operation should always be working. Same as copying content, or cutting content (without the actual delete happening of course).

If you have any other ideas on how we could have prevented this bug, do reach out on Twitter to Martin Middel! We are always looking for feedback and new ideas!

I hope this explained how Fonto works and why it works like that. During the years we built quite the product, and we are aware some parts work in unexpected ways for those who have not been with it from the start. If you have any points of Fonto you would like some focus on, we are always ready and willing to share! Reach out on Twitter to Martin Middel or file a support issue!

Stay up-to-dateFonto Why & How posts direct in your inbox

Receive updates on new Fonto Why & How blog posts by email

Leave a Comment

Your email address will not be published.

Fonto 8.0 WebinarApril 13, 6.30 pm CET / 11.30 am CST

Providing you with insights from our team and a QA session.

Scroll to Top