How to allow people to edit multiple posts at the same time without overwriting each one? - session

I have a site where people can create posts and submit them (like on Stackoverflow and Facebook).
One thing that the user can do is attach a photo before submitting the post. So as soon as the photo is attached (using AJAX), a new PostID is created in the backend database table for the post that's being worked on and stored in the user's SESSION scope e.g. SESSION.LoggedIn.PostID = rsInsertedPost.PostID.
The same things happens even if a photo isn't attached except that it will create the PostID on the final submission of the post instead.
The reason I store it in the SESSION scope is because the PostID that's just been created is used in multiple other areas in the backend application (CFC component in my case). For example, it will insert tags that the user associated with his post into a seperate table dbo.PostTags like such:
PostID | Tag
44 ColdFusion
44 Programming
44 SQL
After it has finished processing the form submission, it will remove the PostID from the user's SESSION.
The problem that I am about to encounter is when a user opens up multiple browser windows and decides to start working on multiple posts at the same time. The SESSION's PostID value will keep being overwritten by the newly created one which means that if they decided to go back to a different browser tab and submit their post it would end up affecting the last created Post.
What would be a good way to overcome this issue of keeping a track of PostIDs that people are currently working on per window. Is there some other unique attribute I could store in the SESSION alongside the PostID so that only that one will be affected per browser window thats open?

I like to use UUIDs. Then I'm sure to never use the same ID twice, not even across database tables.
So instead of setting the PostID to a number (typically 1 + the last id in the database table), use #createUUID()#.

Related

Magento 2: Generating Customer Session Based Caching Pages

Scenario:
In an integration in Magento 2 with Full Caching.
We have two types of customers Type 1 and Type 2. Both these types of customers are saved under same Customer Group we are distinguishing the customers based on a customer type attribute.
Customer of type 1 can belong to different departments (1 to many). When he first visits the site after login, he is redirected to select his department.
This value is saved in customer session, on run time customer can change his department that value is updated in the existing customer session.
When we access a new page we get the updated session, but if we access a page that was accessed earlier, we get the old data from session.
Options tried:
We tried to load the data from customer session factory instead of customer session, but still we are facing the issue. Our understanding is that data which is saved in customer object is loaded as new, but since our data is saved under customer session it is not returning the latest data.
For some section of the page we have used sections to load the data, but in that scenario also, if a page is accessed earlier the correct data is not loaded in first refresh, in second refresh the data is loaded properly.
We also tried to update the session data from AJAX, but that was also not much useful since that data is not getting loaded on the pages.
We also tried to use context variables, but when we log the data while saving the context variable the correct data is logged but when we try to fetch the context data, no data was returned. Also even if different context variable is set for each department, the page seems to be rendered from cache.
We can’t use Cookie since this is sensitive data, this will be the last option.
In Magento 1 we had an option to generate new Cache key by extending app\code\local\Enterprise\PageCache\Model\Processor.php,
Example
if
(isset($_COOKIE[Enterprise_PageCache_Model_Cookie::IS_USER_ALLOWED_SAVE_COOKIE]))
{ $uri .= '_' .
$_COOKIE[Enterprise_PageCache_Model_Cookie::IS_USER_ALLOWED_SAVE_COOKIE];
}
Is there any similar option available in Magento 2. If yes, please share some reference links to integrate the same.

How to prevent two users to edit one row from DB

i am using Spring/Hibernate/ZK. In one tab i get object from DB for editing by user, but second user can open the same tab and the same object for editing . I want to informed second user whit message like "This object is аlready open" and hide buttons for save.Тhus second user can see current data from DB to this object but can`t edint him.Is there a way to check session for this object or another way to do that.
The other answers mostly look at the database, but if all users use the same zk application to access the database, you could keep track of opened objects in the Composer or ViewModel (depending whether you use MVC or MVVM; I'll just call it controller).
Your controller would need a static list of objects that are currently modified. If a user requests to open an object that is not in the list, everything is fine and your controller enables the fields and save button. Otherwise, those are disabled and/or you display a message.
The tricky part is clearing objects from that list. If a user presses the save button, you just remove the object from the list. But what if the user doesn't and just closes the tab or their session just times out? In this case you need a callback, or a mechanism that regularly checks whether the screen is still open.
You could achieve this by adding a zk timer to the tab that pings every now and then and updates the timestamp in your static list (so make it a map). If a new user tries to edit the object, check how old the last timestamp is. If it is old enough (i.e. the previous user saved it or abandoned the screen), allow them to edit it.
Still, you have to think about what to do if a user just keeps the screen open. How long are they allowed to keep the lock on the object? This is an issue in Microsoft Office as well. If multiple users try to open an Excel file from a network location, the first one gets to lock and the others cannot save until that user saves.
You may have additional field which indicates that column is being edited. When first user starts work, the field would be updated. The second user would query object with 'on hold' status and your code would handle this.
Other way - use Hibernate #Version field in your entity. It holds object version which is incremented after every update operation. If second user would save object after first one already saved, it would throw OptimisticLockException which you could handle in your code. More about optimistic and pesimistic locking: Chapter 5. Locking. Related discussions: Hibernate Automatic Versioning and When to use #Version and #Audited in Hibernate?
The best solution is to use Optimistic Concurrency Control with Versioning and when Hibernate throws Concurrency Update issue due to same row is being updated in two transaction then use one of below strategy
First Wins Strategy
Last Wins Strategy
Merge Conflicting Update Strategy
First Wins Strategy is not good solution as it leads to lost update and user will get frustrated that all his work is lost.
By Last Wins Strategy one of user will get error message that you are working on Stale data and start your transaction again . By this way also user can get frustrated due to fact that now again he need to restart operation from beginning but his changes will not lost.
Instead go with Merge conflicting Update Strategy, when Hibernate throws Stale object exception reload screen with new data and user will see updated result and allow him to proceed with latest data. In this user changes will not loss and user will not get error message , just his screen reloads with fresh data and he can decide whether to proceed or not .
You can take example any e-commerce site and you will get one of result of either Last Wins Strategy or Merge Conflicting Update Strategy. Two user can start to by one item but one of user will get message in last screen that item is not stock.

Oracle Apex - Using Multiple tabs with the same session state

I am currently providing support to an existing Oracle Apex 4.2.5 application. One of the pages (Page 1003) contains a process that submits information from the Page 1003 page items (e.g. P1003_ITEM1) to our database tables. The contents of these page items are associated with a primary key (Assessment ID) in the database table to which the page items are submitted. Of a few dozen or so page item variables, the primary key is one of only three variables that are passed in through the URL. The URL is as follows:
https://[DOMAIN]/f?p=[APPLICATION ID]:[PAGE NUMBER]:[SESSION ID]:SELECT:NO:1003:P1003_ENTITY_ID,P1003_ASSESSMENT_ID,P1003_PARENT_ID:353767,700177,5716
We have encountered an issue that occurs when our users load Page 1003 in multiple tabs in their browser for different Assessment#'s. Every time a new Page 1003 is loaded in a new tab, the session variables from the previous tab are overwritten. Regardless of which tab the user submits first, the only variables submitted to the database are the ones from the last tab that was loaded by the user. I've seen a few examples online of how to handle similar issues with other programming languages, but I'd like to know if there is an APEX specific solution that I might have overlooked that can handle this situation.
We'd prefer to pass as few variables as possible in to the page through the URL. In fact, some variable are calculated after the page loads and cannot be passed in through the URL.

MVC 3.0 Protect form content from modification using firebug/developer tools

I have a form (say employee details modification form) where the unique id (say emp id) is kept in a hidden form field and same is available in the model when the form is posted back.
That id will be used for database update.
But user can modify the same using firebug/developer tools. How can we protect it?
I don't know this is the right solution, but you can store the id in session variable and
when you are posting back the form, you can retrieve it from the session and further process it to save in database...

can we store viewstate in masterpage?

Example
I have a gridview having multiple customers.
When a user clicks on the customer link then the CustomerId is stored in the Session "CustomerId".
if i open multiple customer details on multiple tabs then the Session "CustomerId" is overwritten.
so it does not make sense to store customerid in the Session.
I just want to store customerids for different tabs
Is there a way by which i can store the customerid in the viewstate of the masterpage?
(Assuming there is a single master page and multiple content pages.)
I usually try to use the URL for page-specific state info. Using session or some other shared storage can easily get messy. If the amount of state data is a bit much for being passed around in the URL, one way could be to rework the way you store the info in the session. by creating a class for holding the needed data, store several such objects in the session and identifying them by some generated request id. This request id can then be passed in the url to allow the page to pick up the correct state info from the session object.
No. The master page does not "live" between requests to different pages, you will have the same effect as storing the value in the page's viewstate.
I would normally use the querystring for this kind of thing, primarily so that the pages are bookmarkable (if you use sessionstate or form values instead, it's impossible to bookmark the page). As you say in your comment to Fredrik's answer, this does mean that users can manipulate the URL to view different customers, but this isn't a problem provided you're checking that the user is allowed to access the specified customer.
If you really don't want to use the querystring, I'd go with hidden form fields to pass the ID around. You should still be checking whether the user is allowed to see the customer though, rather than just blindly assuming that all's fine.

Resources