logo

An Alternative to Using The ?DeleteDocument URL Command

One thing I've never really liked to do is use Domino's ?DeleteDocument URL command. It just seems so sudden and unforgiving, with no user confirmation required and no way back (apart from soft delete of course).

Although it is quick and easy to use ?DeleteDocument there's little logic to it. In a recent application I developed it just didn't cut the mustard and I had to re-think the way documents were deleted.

The application had a dozen or so different types of documents, based on the same number of Forms. Different people had different roles to perform and thus had varying degrees of access to create, edit and view these documents. The same logic was needed when it came to deleting them. However, the ACL says you can either delete documents or you can't. There's no granular control over what you can and can't delete.

To get round this I moved all the deletion logic in to an Agent. The ID that signed this agent is listed in the ACL as the only entity (be it a person or a server) who has the Delete Documents option ticked. In effect the agent became the only way to delete a document.

As it happens this Agent was the WQS Agent associated with a form called "Delete". To delete any given document you opened this form and passed to it the UNID of the document you wished to delete. The form displayed a message saying "Are you sure you want to delete *title gets inserted here*?" along with a "Yes, I'm sure" button and a "No, cancel this and return me back to the document" link. If you pressed the yes button then it submitted the form and the UNID of the document to delete to the WQS agent where the logic and, ultimately, the deletion of the document happens.

The existence of this intermediate form asking for your confirmation of the deletion has the added bonus of ridding us of the utter finality of using a link to a ?DeleteDocument URL. I've written about a JavaScript addition to the link (seven years ago!) but that requires JavaScript and this form is more accessible.

Another added bonus of using an agent is that you can remove children or other related documents at the same time. If the document being deleted is a discussion topic then you can delete all the responses too. If you used a ?DeleteDocument command on the topic then you would normally leave a lot of orphans. You could even make deletion of child documents an option on the "delete form".

Is this something you're interested in? Hopefully so, as before the end of the work I want to continue on and describe the Agent's logic in more detail and maybe make it available as a demo/download.

Comments

    • avatar
    • Santi
    • Tue 1 Apr 2008 03:24 AM

    Hi Jake

    I agree with you, the delete url it's too direct, but the javascript solution , for single documents with no responses it's all right for me.

    One little question just in case. WQS means Web Query Save ?

    Best Regards form Barcelona

  1. Hi Jake,

    Interested? Yes indeedy. I've shied away from hard deletions in the past because of what you have described above.

    regards

    Alan

    • avatar
    • Jake Howlett
    • Tue 1 Apr 2008 03:40 AM

    Sorry, yes, WQS is a WebQuerySave agent. I'd thought this had become the standard speak for Domino developers?

    • avatar
    • YoGi
    • Tue 1 Apr 2008 03:51 AM

    As far as I can remember, when you delete a document, you delete its responses too. Or am I wrong ?

    • avatar
    • Patrick Ryan
    • Tue 1 Apr 2008 07:51 AM

    Jake,

    Do you do anything (or is there anything you can do) to cater for someone typing the ?DeleteDocument URL directly?

  2. YoGi, if it was like you said, there wouldn't be this brilliant little idea floating around on IdeaJam. ;-P

    {Link}

  3. After having to get the backup dude to restore a 30 gig database 5 times to recover documents that a user had accidetally deleted, I now use a simple method which has actually worked well for us. Here is how it works.

    1. Only the developers have true delete functionality.

    2. Users have an action button that simply renames the form to "Deleted" + the form name. This gives the illusion that the doc has been deleted but it actually just disappears from all views and is collected in a single view that collect all docs where @Contains(form;"Deleted").

    3. An agent run once a week and moves these "Deleted" docs to a separate database (in our case we call it "Recycle Bin".

    4. This method has saved our butts more times than I can count and has sadly proven to me that most users cannot be trusted to have real delete access.

    5. Ya...I know, I am a glass half emtpy kind of guy.

    • avatar
    • John Fazio
    • Tue 1 Apr 2008 09:28 AM

    We use a similar approach as Curt except we set a DeleteDT field instead of changing the form name. A scheduled agent hard deletes those after a set time period like 10 days while making sure it handles responses etc and PostDocumentDelete (Database Script) copies the docs to another database. Additionally a restore action allows specified power users the ability to (obviously) restore any documents marked for deletion.

  4. Interesting idea -- but I'm weary of putting so much functionality into what is basically a UI control... unless I'm missing something.

    If you're written your Agent to accept a "docid" parameter, so you could effectively delete a document by hitting this:

    deletedocument?openagent&docid=123123123123123123123123123213

    You can ultimately expand this deletion engine to accomodate multiple documents:

    deletedocument?openagent&docid=123123123123123123123123123&docid=asdfasdfasdfadsfafdasfdasdfadsf

    The "deletedocument" Agent Design Element would take the values, and you could process the documents accordingly.

    To give you the same functionality of your confirmation form, don't use the WQS event, but rather the $$Return of the form to format your querystring.

    Using this architecture, you could confirm multiple document deletions by displaying the selected documents for deletion (<input type="checkbox" name="docid"....) for a final confirmation.

    This way, if they make a mistake, they can deselect a document for deletion during their confirmation step.

    Hopefully this makes sense... I'm hammering it out while waiting for an conference call with IBMers while sitting in a diner ;-)

  5. YoGi,

    No, descendants are not automatically deleted, but it's easy to write a recursive sub that will schwack all descendants no matter how many levels deep. I can send it to you if you write to me.

    • avatar
    • YoGi
    • Tue 1 Apr 2008 10:55 AM

    Thanks for the reminder.

  6. Hi Jake,

    This is sound architecture from my perspective. You have a controller basically in place for one specific use case to be directed to. All consumers of this service have one place to call to to get the job done. Fairly tidy.

    My only suggestion to improve would be to add an "on behalf of" hidden input as a thin layer of additional security and then log the deletions somewhere. Log the on behalf of user id, the ip address and the document id deleted. With these things, you can at least determine what happened if a question is ever raised. And optionally, security around the user privileges can be built if desired.

    PeopleSoft has (in some implementations) this idea for validating the insert authority for incoming SOAP messaged. If the on behalf of is a user id that is permitted, the insert is executed.

    All this to say, even with a refined control like this, give some attention to auditability. That's something Domino painfully lacks.

    • avatar
    • Brane
    • Wed 2 Apr 2008 03:37 AM

    Hi Jake,

    It would be great to hear more about this topic!

    • avatar
    • Jake Howlett
    • Wed 2 Apr 2008 04:28 AM

    Curt. The agent does the deletion on the very last line. The code before that builds a Notesdocumentcollection (called DocsToDelete) of what needs removing (be it just one document or the document and all it's responses).

    The last line calls DocsToDelete.Remove(). It could just as well call DocsToDelete.StampAll("Deleted", "1") or similar.

    Whether you actually delete or not doesn't matter. It's how you prevent actual deletion by mistake or by hacking.

    Jake

    • avatar
    • swati
    • Fri 30 May 2008 03:10 PM

    Can you HardDeleteDocument using c++ api? or is it available only in the script?

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Tue 1 Apr 2008

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

More Content