How to handle the data concurrency? - php

For instance , in my system i allow the user to create a list and add some information into the list eg. name , address, phone...
And after create the list, it will be inserted into database, and in the page the admin can delete the list
The problem is when user editing the list, the admin deleted the list, then what will happen?
The only way is to check the database again before the edit submit to the database. However, If there are a lot of form, a lot of input, how can i check each field , there is a lot of job if i have to check every field that is concurrent.
I am using php , mysql and pdo for query
Thank you

Well why wouldn't you simply check if the row exists in the corresponding table using it's primary key (id) ?

Basicly, you cannot avoid that situation. While the user edits the form, the user cannot find out if the form has been deleted.
One solution would be to have a flag up once the user starts editing the records that should prevent anyone from editing at the same time/deleting at the same time. Once the user submits the form, then the flag should be back to original value, so that other users/admins can edit/delet those records.
There is a second solution of using a service and check from time to time in the user's page via ajax if the records are still there, but if you have alot of inputs, that can be a little cumbersome to implement.
Basicly, you need to create something that resembles a transaction, aka. lock the records that are being edited. Be very carefoul, since you can end up with alot of locked records. You need to implement a time in which the user needs to finalize the "transaction". If there are locked records beyond that time, unlock them automaticly. Also beware of the fact that the user might exceed that time and you need to handle that situation also, since you will end up in the same state as your original problem.
PS: also you need to beware of informations that have been edited while the user was editig also, since those informations would be lost. For the edit part, i think i would go for a hashing approach to check the state before editing with the state after editing. from this point on, it's up to you to decide what to do.

Related

Real time data with Angular

i want to create a web page with data, this data can be edited in Real Time.
Users will see data in Real Time and can edit it, something like "Google Sheets" where everyone can edit the same file and see others changes in real time.
I will be using PHP, MYSQL, AngularJS.
I want to consult you on how to do it in the best way, this is some points that i thought of:
Use angular polling every X seconds to update page data in real time, but if user editing one of the fields, how can i prevent from this specific field to be updated by polling?
How can i LOCK specific field that user is editing, to prevent 2 users to edit the same field in real time
There is any better way to pull data in real time than angular polling?
When user editing text field i want to update it in database without "submit" or save button, i thought to save the data after 3 seconds, any better ideas?
Thank you,
1:
I'd suggest for you to have an array of objects or a datastructure similar to that, which contains the fields, in your AngularJS controller. When a user starts editing a certain field, you could set isEditing to true in the field object in your datastructure. Whenever an update comes in, you loop through your datastructure and only update fields of which isEditing isn't set / isn't true.
For making it more realtime, instead of polling, setup WebSockets and let the server broadcast the newest values of a field to all editors whenever it gets changed.
2:
For locking a field that a certain user is working on, you could add a locked column to the database table containing the fields. Whenever a user wants to start editing, the following would occur:
User requests to edit a field
Server checks if the field is locked
If the field isn't locked, the user is permitted to edit the field and the server sets the locked column to true or to the username, depending on your needs.
If the field is locked, the user isn't permitted to edit the field
When a user saves a field after editing it, you should set the locked column to false. You should probably also set the locked column to false whenever the editing user gets disconnected.
3:
PHP on it's own is not able to send data to the client without the client making a request. You'd need to add WebSocket support to PHP (for example http://socketo.me/, haven't tried that out though).
If you are interested in a server platform that is able to do this out of the box, you could take a look at http://nodejs.org. When you plan on using Node.js, I suggest using http://socket.io/ for maximum browser compatibility. (it includes fallbacks for whenever WebSockets aren't supported by the users browser)
4:
You could save the current value every x seconds if the value is different from the previous save. This would be more efficient than always saving the value. You'd need to save the previously saved value in a variable for this.

Should I delete MySQL entries using a PHP script which users can run?

I'm currently working on a website which will have many users on it. These users are stored in a table with each having a unique id. The website will contain projects that the users can complete and these projects are stored in a separate table with unique id's as well.
I need to make the users have a page they can view which will display a list of all the projects they are currently working on.
To do this, I am going to set up another table in which each row will have the user's id as well as the project's id that they are working on. All of that will work alright but I would like to allow users to cancel their projects if they please. I am aware of how to do this, but I have read that deleting rows directly from a php script is insecure so the user used to access the database from PHP does not have 'DELETE' permissions. I am wondering if I should just delete rows at will when a user specifies which project to delete or if I should just have another field and simply mark each user-project row as being 'cancelled' in another field so I can work with them myself.
What you should do is, for maximum security is, have a parameter in the database table called "isActive", or something of that nature, that is a BIT data type to represent a boolean. If that boolean is false, then do not delete the project from the database, simply hide that tables data (do not display it on the site, but keep the data stored in the databse). That way, not only is your database secure from malicious users who would like to destroy data, but projects can also be "re-instated" if they wish to re-instate it. If the project sits around for a certain period of time, say, 14 days, just have the server delete it, not the user, if you wish. This worked for me in the past.
Hope This Helps!
The most common approach to this problem is to have a field in the table that can be used to mark a record as deleted. This would be the only access the general user would have to the table as far as deletion goes. Some people also have a full delete, which states clearly that it will never be accessible again after the operation is completed.
Personally, I prefer to retain full delete permission to administrators allow the user to only mark records as deleted. If you're concerned about space, add a last accessed field as well, and schedule at set intervals a call to perform a full delete on any records that are marked as deleted and have not been active for a certain amount of time.

How do I prevent people from opening a record if someone else has it open?

I'm creating a PHP Web application, which would involve:
1) Users opening a record
2) Users making changes to the record
3) Saving changes to the record
Since this is a multi-user application, I want to prevent situations where two users have the same record open at the same time, and one user's changes overwrites the next, preferrably by enforcing some sort of locking method when a record is opened that automatically unlocks when the user navigates away from the page.
By record, you mean SQL records? If so, you could add another column isOpen. Set it to 1 as long as someone else has it open, and in that case, do not serve it to anyone else.
In situations like this, it works best to also implement a timeout mechanism, where a record can be open only for 'x' min before being forcibly closed.
(Edit: This answer is assuming you want to keep a record locked the entire duration a user is viewing the info fetched from the table. If you want to lock a record only for the instant that a read/write operation is occuring on that record, MySQL engines have inbuilt mechanisms for that)
In response to your comment
To make a record accessible to others when the active user navigates away, off the top of my head, I can think of two ways to achieve it:
Allow the timeout mechanism to take care of it. Depending on your scenario, a short enough time window could work fine.
In addition to the timeout, also implement a heartbeat mechanism - an Ajax script on the page polls the server letting it know the page is still open. If the user navigates away, the server recognizes the skipped heartbeat, and unsets the record. In this case, the timeout would still take precedence. So, if the user leaves the window open and walks away, the server would still receive the heartbeat, but when the time window closes, the server unsets the record (despite still receiving heartbeats).
I use a field update_date. When user reads the record I write a cookie with this date. When user updates the record and submits the new data I'am adding WHERE update_date = '$my_escaped_date' AND id = '$the_edited_id' and if mysql_affected_rows is zero I'm showing error message that the edited data is old. It's not perfect as if you edit old data you must reenter it, but it does the job.
A locking method is exactly what is available in mysql:
http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
It's not automatic but it allows you to lock a table, do stuff and then unlock it again.
Be carefull tho' that the system does not become locked up if you forget to unlock a table or a user takes a long time to change something and you only unlock it when that user submits the form.
A better way might be to read data from the table and upon submission of the form, check to see if the data has not been altered. If it has you can notify the user of the changes and other wise you can lock the table, perform the changes and unlock it again.
You can add a field in_use to the records table,
when a user open that record update its value to 1 and when he saves it
update it back to 0.
If the value is 1 - the record is locked and won't be opened for other users.

Soft Delete VS Hard Delete

I am building a system that will use a commenting based ticket system. I would like to get some opinions around the idea of flagging a user as deleted or removing the record completely.
Ideally I want to keep the system free of old accounts but at the same time by deleting a user the commenting within the ticket system may not make sense.
Has anyone come up with a solution to this type of problem. My ideas so far:
Delete the users account, comments and all other relevant data.
Flag the user as deleted and create a brand new account if they subscribe again.
Flag the user as deleted but if the user was to try to subscribe again update and unflag as deleted instead of adding a new one.
Delete the user account only. Then when fetching comments etc. check for an associated id, if no result found then display the comment with a message "the users account has been deleted".
What do you think?
I would say that the third option is the best choice
My reasoning for this is any tickets stored in the database should be kept for the life of the database, if you attempt to delete a user from the database, you will remove that users reference to any tickets in the database.
(Thats if the database will let you delete it since the user's id will be linked to any tickets he/she may have created)
When that user goes to create a new account in the ticketing system, the tickets that he may have created months ago have dissapeared and may now have been created by null.
I would always use the last solution: delete the user account only and show an "account deleted" message if the poster's account doesn't exist anymore. If you don't allow users to change their username, you can also save the poster's username (beyond his ID) and display it as plain text if the user deleted his/her account, or as a link if the user is still active.
If you're representing the user <-> comment relationship with a FOREIGN KEY, you can't delete the user without deleting the comment or updating the comment's associated user to either NULL or to point to some "deleted user" fake user account (in either case, losing the information about the user who posted the comment).
The ticketing system I wrote basically did number 3. Anything else will ruin any audit trails you need to keep.
If you need to get rid of old stuff one way is to set cleardown of old tickets. Then, when all related tickets for an account are gone, you can remove the account.
It really depends on you use case.
Personally I would never delete stuff like user-accounts from a db completely.
So option 1 is out. (but that's just me)
Option 2 has the problem, that you'll have lots of dangling user-accounts.
Option 3 looks like the best option -cough- audit trail -cough-
Option 4 is asking for trouble, you have a link to another table, but that data has been deleted.

What's the safest way to remove data from mysql? (PHP/Mysql)

I want to allow users as well as me(the admin) to delete data in mysql.
I used to have remove.php that would get $_GETs from whatever that needed to be deleted such as... remove.php?action=post&posting_id=2. But I learned that anyone can simply abuse it and delete all my data.
So what's the safest way for users and me to delete information without getting all crazy and hard? I am only a beginner :)
I'm not sure if I can use POSTs because there is no forms and the data isn't changing.
Is sessions good? Or would there be too many with postings, user information, comments, etc.
Ex: James wants to delete one of his postings(it is posting_id=5). So he clicks the remove link and that takes him to remove.php?action=post&posting_id=5.
EDIT: Alright, so now I am a little confused. While I can't be 100% secure, how do I do this with $_POSTs?
SOO I should use GETs to get all the data to remove.php, THEN have a confirmation submit button and when users click on it, it put all the data into POSTs and delete from the dbc?
Deleting records is a kind of a scary practice. If you or someone makes a mistake there's no real recourse to resolve the issue. Expunged records are very hard to resurrect.
Instead of deleting records, you could add an "active" bit (e.g. Boolean) column that is toggled off when users "delete" records. Essentially your users would be suspending records by toggling them off and the records would be saved in case mistakes or abuse but appear "deleted" to the user. To make this work with your other queries, just add a where clause of active = 1.
You could then have a utility script that's run at some specific date interval that would clean out deprecated, past dated records. You'd also need some type of timestamp for this type of maintenance.
Just a thought. Take if for what it's worth.
I'll echo gurun8 in preferring to 'mark' records as deleted, instead of actually removing data. And then obviously, you'll need to check that the authenticated user has permission to delete the post.
However, it seems very important to mention that $_GET is not safe even with authentication because of cross-site request forgery.
Imagine if Amazon adding things to your cart based on a GET request. All I'd have to do is put an image on my page with that URL, and everyone who visited that page and logged into Amazon will have products added automatically.
To match your example, I don't like Jame's post, so i put an image on my site like this:
<img src='http://example.com/remove.php?action=post&posting_id=5'>
And I send him a link to my page, and ask him to check it out, hoping that at the time he's logged in to your site. Because, of course, he clicked that little 'keep me logged in' button.
So you are right to be concerned about using GET. If you don't want to litter pages with forms, then confirm the action by POST.
Well you have to start by authenticating the users with a login script.
If you want the simplest solution possible, then I'd suggest protecting the directory in which you have remove.php with a simple .htaccess username and password.
If different users have different rights for deleting database entries, then you probably should create a PHP login script and use PHP session.
Bonk me if I'm stupid, but I searched for quite some time for a simple PHP login tutorial that could be placed on a real site (doesn't use session_register(), uses mysql_real_escape_string(), htmlspecialchars() etc) and I simply couldn't find one!
Probably this one comes the closest, you just have to replace session_register() variables with $_SESSION ones for it to work without register_globals (default in PHP5).

Categories