ReSet all password status to zero using trigger - mysql

I am optimizing my login system in which I am maintain previous passwords of a user, schema of pwd table for maintaining passwords is as follows:
here userId refers to primary key of user table.
If status attribute is 1 that means row has marking current password if it is 0 previous password.
How can I write a trigger so that if a new entry for any user is made in pwd
table, all previous status of that user gets set to 0 and new value will remain 1 as the default value of status attribute. Currently I am doing so at application level.

It won't be possible because it would require to have a mutating (changing the same table it's being fired upon) trigger which is prohibited in MySQL.
You can create a stored procedure though, but you would still need to call it from the client code explicitly.
Now a better schema design would be to keep all current passwords in one table (presumably in the users table) and all previous in the other (i.e. pwd_history). Not only it makes queries for current passwords faster it also allows you to use a trigger if you choose to.
DELIMITER //
CREATE TRIGGER tg_pwd_history
AFTER UPDATE ON users
FOR EACH ROW
BEGIN
IF NOT NEW.pwd <=> OLD.pwd THEN
INSERT INTO pwd_history (`userId`, `pwd`, `ts`)
VALUES (NEW.id, OLD.pwd, NOW());
END IF;
END//
DELIMITER ;
Here is a SQLFiddle demo
Now I very much hope you're not storing them in plain text.

Related

Protecting database data

Currently I'm using a MySQL database. Let's say that I have some data regarding last month. When the data has been verified I want to "lock" it, so when my boss asks me if the data is correct, I can answer yes, because I'm certain that the data couldn't have been altered in the mean time.
Is there a way to "lock" data rows or cells from being modified? How could I do that?
Mysql innoDB lock may works, but is not permanent I think (related to transactions). Check yourself here
I would suggest you add an extra column in your table, name it for eg. validated with default value 0. Then when every rows are validated, you change validated value to 1. If so, you can add a trigger to check update on this current table.
delimiter $$
CREATE TRIGGER updateRestrictionOnMyTable
BEFORE UPDATE ON my_table
FOR EACH ROW
BEGIN
IF OLD.validated > 0 THEN
SIGNAL SQLSTATE VALUE '99999'
SET MESSAGE_TEXT = 'You cannot update validated rows';
END IF;
END$$
delimiter ;

Eliminate possibility of belated data manipulations on MySQL table

I want to guarantee that the rows in my MySQL table cannot be manipulated after their creation.
I know that only granting insert and select privileges is one step in this direction, but I also want to make sure the root user cannot alter data after insertion.
Incremental hashing:
To this end, I think about an additional column 'hash', that stores the hash value of the last row's hash concatted with the new column data.
If I then export the hashes eg. every day, any manipulation could be detected.
Am I right? Can you point me to some resources where this has been done already? Would one do this with a trigger? Maybe even in an auxiliary table that is only accessible by root?
Something like that :
DELIMITER $$
CREATE TRIGGER trigger_hash
AFTER INSERT
ON table_name FOR EACH ROW
BEGIN
UPDATE table_name
SET hash = MD5(concat(NEW.field1, NEW.field2, NEW.field3, ...))
WHERE id= NEW.id
END;
$$
DELIMITER ;

creating a trigger to lock and unlock a record

I am creating a php script for a MySQL database whereby I call a MySQL trigger..
The trigger should affect a table which is effectively an invoice:
So when I update a field called 'date_invoiced' from its NULL default to a valid date it then locks the whole record from being updated unless you have permission via your MySQL logon to change it back to its default NULL, (effectively 're-opening' the invoice)
No idea how to do this, any help would be great
You can't put a lock on a row. I suggest you use a TRIGGER on update, which makes the update fail if date_invoiced is NOT NULL. Unless username is 'superman'.
I think that you can code what you want following this example.
DELIMITER ||
CREATE TRIGGER upd_lock
BEFORE UPDATE
ON table_name
FOR EACH ROW
BEGIN
IF OLD.date_invoiced IS NOT NULL AND USER() NOT LIKE '\'superman\'#%' THEN
SIGNAL SQLSTATE VALUE '45000' SET MESSAGE_TEXT = '[upd_lock] - Record is locked';
END IF;
END;
||
DELIMITER ;
Adding triggers is essential for the development of complex MySQL databases that retain enforced referential integrity. Foreign keys cannot handle complex cases that perhaps involve more than one column (such as an item_id and item_type_id scenario).
SUPER is required when creating or dropping trigger only when binary logging is turned on.
The reason appears to be related to replication issues (MySQL 5.0 documentation).
RTM.and RTM
Read this link to ... & this threads Applying column permissions for a table over a trigger , Can't create MySQL trigger with TRIGGER privilege on 5.1.32

Trigger on a field is fired unexpectedly when I update another field

Here is my table:
Id Password Status
1 a6cc890.. 1
I have a trigger upon Password which is used to encrypt the field.
The trigger is as below:
-- Trigger DDL Statements
DELIMITER $$
USE `ediftpdb`$$
CREATE
DEFINER=`edidbo`#`%`
TRIGGER `ediftpdb`.`trigger_format_passwd`
BEFORE INSERT ON `ediftpdb`.`users`
FOR EACH ROW
SET NEW.passwd=md5(NEW.passwd)$$
CREATE
DEFINER=`edidbo`#`%`
TRIGGER `ediftpdb`.`trigger_format_passwd_update`
BEFORE UPDATE ON `ediftpdb`.`users`
FOR EACH ROW
SET NEW.passwd=md5(NEW.passwd)$$
To my surprise, the trigger is fired when I update Status, and the password is encrypted again!
What should I do to resolve this issue?
If you update Status, you're doing an UPDATE and all of the UPDATE triggers will fire. All you need to do is compare the new and old values of passwd and only apply your MD5 if they are different. Lucky for you, MySQL supplies OLD and NEW row aliases:
You can refer to columns in the subject table (the table associated with the trigger) by using the aliases OLD and NEW. OLD.col_name refers to a column of an existing row before it is updated or deleted. NEW.col_name refers to the column of a new row to be inserted or an existing row after it is updated. Try using IF:
BEFORE UPDATE ON `ediftpdb`.`users`
FOR EACH ROW
SET NEW.passwd = IF(NEW.passwd = OLD.passwd, NEW.passwd, md5(NEW.passwd))
This shouldn't change NEW.passwd unless NEW.passwd (the new password) and OLD.passwd (the hashed password that is already in the database) are different. Of course, this might fail if someone manages to enter the MD5 of their old password as their new password but that's pretty unlikely.
When you "update Status", you're actually performing an UPDATE on the whole table. The fact that you only modify the value of one field doesn't come into it!
You can manually check whether the value of passwd has changed using the NEW and OLD identifiers.

Use mysql user in trigger

I'm creating a trigger in MySQL to let me know WHO (which mysql user) is doing an update on a specific table.
I know MySQL has a function CURRENT_USER(), but is that going to insert the username at the time the trigger is CREATED, or at the time the trigger is CALLED?
This is my trigger so far. I want to insert the username in the 'content' column.
delimiter |
CREATE TRIGGER update_product_procedure
BEFORE UPDATE ON product_procedure
FOR EACH ROW BEGIN
INSERT INTO trigger_logs SET
content = 'This is a test', postDate=NOW();
END;
|
I would have put lots of money on it being the invoker, but from http://bugs.mysql.com/bug.php?id=5861:
SQL standard says that: "A triggered action is always executed under
the authorization of the owner of the schema that includes the trigger." This means that
in MySQL we should execute trigger body under authorization of user who
created trigger and not the one who issued statement which invoked this trigger.
Apologies, I assumed it was an obvious question :-(
Regards
EDIT: user() gives the invoker