Intermediate save and readonly after termination - orbeon

We have the requirement that users, after terminating the input of a form, can only see the data; only authorized users can modify the data.
For this purpose we use the following permissions and it works smoothly:
Now raised a second requirement.
The users wish the possibility to finish the input of the form in a second moment, so that they don't have to fill in the form entirely after pressing the new button, before they can push the save button.
Because some forms are large and maybe they are in a hurry to catch the bus, or maybe for some answer they have to ask someone else not contactable at the moment.
The idea was to add the save-draft button.
The first save-draft is OK; the message is "Draft saved successfully!".
But the second save complains:
It seems that the permissions don't differentiate between save and draft-save, so that also after a draft-save the form data is read-only.
Which possibilities I have to achive this two goals?
Many thanks.

The save-draft process is very much like the regular save (save-final process), except that it lets users save data even if the value of some fields is invalid. So, indeed, from the perspective of the permissions, save-final and save-draft are the same.
What you would really need is the ability for:
A process to save the stage of the form along with the data. In your case, the stage could be "work in progress" or "submitted".
The permissions to be able to depend on that stage, so you can say "users can edit their own data if the stage is work in progress, but can only view it if the stage is submitted".
You can do #1 right now using a hidden field and an xf:setvalue() action. But you can't do #2. For that, you would need the workflow feature to be implemented (see RFE #2256), which we hope to be able to complete in 2018. So, you guessed it, the good news is that this is coming, but the bad news is, at least as I write these lines, that it isn't implemented yet.

Related

Creating history or log for certain events

I am not sure what is better perfomance whise so I ask you guys.
The problem is following:
I have a system where each User gets a certain amount of credit for certain events. So I gave my User an attribute named creditscore that gets altered on those events. Everything works well. But now I want the user to actually see what he did when and how much credit he got for this.
What would be better here:
Saving the whole history in a text attribute and add lines for each event
or
writing an extra model associated with the user and create an instance for every event.
or
or
something way different?
Since there are several events per user per day it would be either a huge text or a huge amount of instances. What would be better looking at website performance.
You absolutely do NOT want to store the history in a text attribute. Management of this will be a nightmare as will querying the data.
You could create a CreditEvent model and store the individual events in there. That would work fine.
However, before you start, check rubygems.org and ruby-toolbox.com to see if someone has already done the hard work. I know of at least one gem that seems to do exactly what you want to do:
https://github.com/merit-gem/merit

Rails 'Preview State' Using Cookies/Session

This seems to be a common question, but I've yet to find a very 'detailed' answer - I'm looking for the best way to allow users to preview the form they are going to submit, before submitting it.
Obviously, storing this in the db isnt the best option (which is what I'm doing right now) because there has to be a process to remove it, and that has a lot of scenarios.
Details
I don't want to show the user the edit action, I want to show the user the show action, and at the top and bottom of the screen have a Publish button.
My questions:
How would you go about storing the information from the form into a session (looking for some controller code)
How would you know in the show action that you are displaying a preview, rather than a 'real' object. (or would you have a separate action for preview?) (looking for some controller/view code here)
How would you remove the session data once the user is 'done' with it?
I think that storing in the database has the same issue with storing it in the session, the cleanup, am I wrong? What is the best way to do this?
You can consider unpublished records created more than few days ago as obsolete (user must know about that policy). Rake task may be executed via cron once a day or more frequently. Also, you can implement some separate rake task to notify users about pending unpublished records, which will be removed soon. Drafts is a great idea and may be untouched if you like at all or for a longer time.

Saving state between actions

I'd like to ask for a solution. For example we have a page. And I have a link to a another action from this page. I want to have an ability to save the values of entered data on the page.
For instance I go to another page enter data and go back. Like the wizard. But the problem is that we can come to the action from different pages. And it need to save several data types.
Is it understand?
Any suggestions?
I'd like to have common solution....
You could also use TempData to persist data between requests.
In the past for wizards I have used Session to store data as it gets built up along the way.
One thing to not forget is to validate the data you are storing in the session everytime you go to use it. If not a user can exploit the back button to fake certain scenarios. For example:
User uses the wizard and gets to step 3 in the wizard.
They then go to another page that is not part of the wizard.
Then the user enters the wizard again and
only gets to step 2 of the wizard.
User then uses the back button to go all
the way back to the original wizard
that they were on step 3 for.
In this case the data in your session if posted will think it came from the original wizard even though the data in the session is reflecting only up to step 2 from when the user accessed the wizard the second time. Use a unique key each time someone starts a wizard and validate it at each step.
Hope that helps and isn't too confusing (it was a bit to me typing it).
An alternative is to persist the data via the TempData but each time you will need to pull it out and persist it for posting back to the next step. Then rebuild it, add to it and repeat. This can be a lot of work as well but at least you don't have to worry about things happening out of synch.

How do I update only the properties of my models that have changed in MVC?

I'm developing a webapp that allows the editing of records. There is a possibility that two users could be working on the same screen at a time and I want to minimise the damage done, if they both click save.
If User1 requests the page and then makes changes to the Address, Telephone and Contact Details, but before he clicks Save, User2 requests the same page.
User1 then clicks save and the whole model is updated using TryUpdateModel(), if User2 simply appends some detail to the Notes field, when he saves, the TryUpdateModel() method will overwrite the new details User1 saved, with the old details.
I've considered storing the original values for all the model's properties in a hidden form field, and then writing a custom TryUpdateModel to only update the properties that have changed, but this feels a little too like the Viewstate we've all been more than happy to leave behind by moving to MVC.
Is there a pattern for dealing with this problem that I'm not aware of?
How would you handle it?
Update: In answer to the comments below, I'm using Entity Framework.
Anthony
Unless you have any particular requirements for what happens in this case (e.g. lock the record, which of course requires some functionality to undo the lock in the event that the user decides not to make a change) I'd suggest the normal approach is an optimistic lock:
Each update you perform should check that the record hasn't changed in the meantime.
So:
Put an integer "version" property or a guid / rowversion on the record.
Ensure this is contained in a hidden field in the html and is therefore returned with any submit;
When you perform the update, ensure that the (database) record's version/guid/rowversion still matches the value that was in the hidden field [and add 1 to the "version" integer when you do the update if you've decided to go with that manual approach.]
A similar approach is obviously to use a date/time stamp on the record, but don't do that because, to within the accuracy of your system clock, it's flawed.
[I suggest you'll find fuller explanations of the whole approach elsewhere. Certainly if you were to google for information on NHibernate's Version functionality...]
Locking modification of a page while one user is working on it is an option. This is done in some wiki software like dokuwiki. In that case it will usually use some javascript to free the lock after 5-10 minutes of inactivity so others can update it.
Another option might be storing all revisions in a database so when two users submit, both copies are saved and still exist. From there on, all you'd need to do is merge the two.
You usually don't handle this. If two users happen to edit a document at the same time and commit their updates, one of them wins and the other looses.
Resources lockout can be done with stateful desktop applications, but with web applications any lockout scheme you try to implement may only minimize the damage but not prevent it.
Don't try to write an absolutely perfect and secure application. It's already good as it is. Just use it, probably the situation won't come up at all.
If you use LINQ to SQL as your ORM it can handle the issues around changed values using the conflicts collection. However, essentially I'd agree with Mastermind's comment.

Preventing double HTTP POST

I have made a little app for signing up for an event. User input their data and click "sign me in".
Now sometimes people are double in the database, the exact same data that got inserted 2 times very quickly after each other. This can only mean someone clicked the button twice, which caused two posts to happen.
This is common web problem, as credit card apps and forum apps often say: "Clicking once is enough!".
I guess you could solve it by checking for the exact same data to see if the post is unique, but I wonder if there are other methods.
This ofcourse does not count for ASP.NET webforms, because POST doesn't matter as much.
While JavaScript solutions can disable the submit button after it has been clicked, this will have no effect on those people who have JavaScript disabled. You should always make things work correctly without JavaScript before adding it in, otherwise there's no point as users will still be able to bypass the checks by just disabling JavaScript.
If the page where the form appears is dynamically generated, you can add a hidden field which contains some sort of sequence number, a hash, or anything unique. Then you have some server-side validation that will check if a request with that unique value has already come in. When the user submits the form, the unique value is checked against a list of "used" values. If it exists in the list, it's a dupe request and can be discarded. If it doesn't exist, then add it to the list and process as normal. As long as you make sure the value is unique, this guarantees the same form cannot be submitted twice.
Of course, if the page the form is on is not dynamically generated, then you'll need to do it the hard way on the server-side to check that the same information has not already been submitted.
Most of the answers so far have been client-side. On the server-side, you can generate a hidden field with a GUID when you first produce the form, and then record that GUID as a submitted form when the post is received. Check it before doing any more processing.
Whenever a page is requested from the server , generate a unique requestToken , save it in server side,mark status as NOT Processed and pass it along with the current requested page. Now whenever a page submit happens , get the requestToken from the "POST"ed data and check the status and save the data or take alternate action.
Most of the banking applications use this technique to prevent double "POST"ing.So this is a time proven & reliable way of preventing double submissions.
A user-side solution is to disable the submission button via Javascript after the first click.
It has drawbacks, but I see it often used on e-commerce websites.
But, it won't never replace a real server-side validation.
Client side techniques are useful, but you may want to couple it with some server side techniques.
One way to do this is to include a unique token in the form (e.g. a GUID or similar), so that when you come to process the form you can check to see whether the token has already been used, preventing a double submission.
In your case, if you have a table with event visitors, you might include this token as a column.
A client-only solution won't be enough, as stated in many of the answers here. You need to go with a server-side fail-safe.
An often overlooked reason that disabling the submit button doesn't work is, the user can simply refresh the submit target (and click OK on the "are you sure you want to resubmit the POST data?" dialog). Or even, some browsers may implicitly reload the submitted page when you try to save the page to disk (for example, you're trying to save a hard-copy of an order confirmation).
Almost no one has js disabled.
Think about coding your e-commerce website for the 70 year old woman who double clicks every link and button.
All you want to do is add a javascript to prevent her clicking "Order Now" twice.
Yes - check this at the server side too "be defensive" - but don't code for that case. But for the sake of a better UI do it on the client side too.
Here are some scripts that I found:
//
// prevent double-click on submit
//
jQuery('input[type=submit]').click(function(){
if(jQuery.data(this, 'clicked')){
return false;
}
else{
jQuery.data(this, 'clicked', true);
return true;
}
});
and
// Find ALL <form> tags on your page
$('form').submit(function(){
// On submit disable its submit button
$('input[type=submit]', this).attr('disabled', 'disabled');
});
None of the solutions address a load-balance server.
If you have some load balancer, send a UUID (or any type of unique number) to the server to store and read again will not work well if the server is not aware of other servers, because each request could be processed by a different server in a stateless environment. These servers need to read/write to the same place.
If you have multiple servers you will need to have some shared cache (like a Redis) among the servers to read/write the unique value in the same place (what could be an over-engineering solution, but works).
Client side alteration is a common technique:
Disable submit button
Change the screen to a "please wait" screen
If the form was modal, changing the screen back to their usual process (this has the benefit of making things look really slick)
But it's not perfect. It all relies on JS being available and if that's not the case, without back-end duplication detection, you'll get duplicates still.
So my advice is to develop some sort of detection behind the scenes and then improve your form to stop people with JS being able to double-submit.
You can track the number of times the form's been submitted and compare it to the number of unique visits to the page with the form on it in the session.
Beside the many good techniques already mentioned, another simple server-side method, that has the drawback of requiring a session, is to have a session variable that is switched off on the first submit.

Resources