Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent race condition when using edit forms in GUI #11732

Closed
tyler-8 opened this issue Feb 10, 2023 · 5 comments
Closed

Prevent race condition when using edit forms in GUI #11732

tyler-8 opened this issue Feb 10, 2023 · 5 comments
Assignees
Labels
status: accepted This issue has been accepted for implementation type: feature Introduction of new functionality to the application
Milestone

Comments

@tyler-8
Copy link
Contributor

tyler-8 commented Feb 10, 2023

NetBox version

v3.4.4

Feature type

Change to existing functionality

Proposed functionality

In edit forms for primary models, when confirming/saving your changes, add a new validation check that the last_updated time has not changed from when you first started editing the object.

If the last_updated time is captured at the time the edit form is loaded, and check again when the Save button is clicked, we can check that the timestamp is the same as before, before finally saving the new change. Otherwise, a validation error is raised.

Use case

It's possible for two users to be editing an object in the GUI at the same time and overwrite each other's changes. Here's the scenario:

  1. Bob creates a Site.
  2. Joe clicks “Edit” on that Site and has the Edit Site form open.
  3. Bob also clicks Edit on the same Site and makes some changes, clicks “Save”.
  4. Joe make changes on his Edit Form and clicks save.
  5. Bob’s changes are no longer present, and Joe’s change is - based on outdated data.

Database changes

N/A

External dependencies

N/A

@tyler-8 tyler-8 added the type: feature Introduction of new functionality to the application label Feb 10, 2023
@jeremystretch
Copy link
Member

Typical Joe. I've been saying we ought to fire that guy.

This is a great idea, and we should be able to implement it pretty seamlessly for (nearly?) every model form.

@sleepinggenius2
Copy link
Contributor

For APIs, I've used the ETag/If-Match header method to support this in the past. For server-rendered pages, I suspect you could use something similar via form fields. Ideally, a similar method would be used for changes made via UI, REST API, and GraphQL (if that supports mutation).

@jsenecal jsenecal added the status: under review Further discussion is needed to determine this issue's scope and/or implementation label Feb 16, 2023
@tyler-8
Copy link
Contributor Author

tyler-8 commented Feb 16, 2023

For APIs, I've used the ETag/If-Match header method to support this in the past. For server-rendered pages, I suspect you could use something similar via form fields. Ideally, a similar method would be used for changes made via UI, REST API, and GraphQL (if that supports mutation).

I'd be hesitant to have this validation (using this particular logic) happen in the API. The additional query to lookup the "in between" last_updated value would likely slow down response times (which would be compounded in high request volume environments). In the GUI you're working at "human speed" so the likelihood of the issue manifesting goes up, but API work tends to have very fast turn around.

@sleepinggenius2
Copy link
Contributor

My previous implementation was using the API for a SPA UI, so it already had to make a request to load the object for the view anyway. Depending on how the REST API is implemented here, you should be able to just issue a HEAD request to get the ETag, without having to retrieve the full resource. Those values could potentially leverage the redis cache, which should make the extra request negligible. However, if you are using only the API to update resources, then you should only need to grab the value once, then cache the ETag from the response each time a change is made, to use in the next request. If you are expecting a mix of UI and API changes on the same resource, then you're just going to run into the same potential for a race condition if you don't use the same safeguard in both places. It would also be dangerous in that circumstance to not already be retrieving the resource to validate current state before making the change via the API. This solution should actually be faster in that scenario, because if your request succeeds with the cached ETag value, then there is no need to make that additional request, as the current state has already been validated.

@jeremystretch jeremystretch added status: needs owner This issue is tentatively accepted pending a volunteer committed to its implementation and removed status: under review Further discussion is needed to determine this issue's scope and/or implementation labels May 2, 2023
@github-actions
Copy link

github-actions bot commented Aug 1, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide.

@github-actions github-actions bot added the pending closure Requires immediate attention to avoid being closed for inactivity label Aug 1, 2023
@jeremystretch jeremystretch self-assigned this Aug 1, 2023
@jeremystretch jeremystretch added status: accepted This issue has been accepted for implementation and removed status: needs owner This issue is tentatively accepted pending a volunteer committed to its implementation pending closure Requires immediate attention to avoid being closed for inactivity labels Aug 1, 2023
@jeremystretch jeremystretch added this to the v3.6 milestone Aug 1, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 31, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status: accepted This issue has been accepted for implementation type: feature Introduction of new functionality to the application
Projects
None yet
Development

No branches or pull requests

4 participants