[Solar-talk] Working with hashes (MD5) and column updates

Raymond Kolbe rkolbe at gmail.com
Tue Jan 1 10:15:18 CST 2008


Hey all,

I've created a filter called sanitizeMD5 that creates a hash out of a
string. I've applied it to my users model (Vendor_Model_Users) so that my
password col would be made into a hash at the appropriate time. Works great,
except for one thing.

When I want to update the user record (let's say we are doing this in
Vendor_App_UserAdmin::actionEdit()) I use Solar_Sql_Model::fetch() to get
the record, use Solar_Sql_Model_Record::load() to load my posted data into
the record, and use Solar_Sql_Model_Record::save() to save the record. This
is the same method used in Solar_Apps to save bookmarks, etc.

The problem is that even though I did not call the password col to be
updated (note: I did not pass 'password' as one of the cols in the whitelist
for Solar_Sql_Model_Record::load()), the password is being hashed each time
on save(). The reason for this is because Solar_Sql_Model::fetch() loads all
cols into the record we fetched. On save() (or rather on
Solar_Sql_Model_Record::_update()), the filters are run to keep the data in
check in the database but what is happening is that sanitizeMD5 is being run
on a hash itself, thus changing a user's password -- not good.

For controllers that do handle updating a user's password, I can not move
the md5 hashing logic into the controller for a couple reasons: A) Why hash
in the controller? This is not the correct place to put the hash logic. B)
If we hash the string (raw user's input) before we run our other filters (to
validate length perhaps) in the model, some will return false positives.
Let's say we wanted to make sure a user's password was between 4 and 10
characters. We would setup a filter in the model that would check this (e.g.
Solar_Filter_ValidateRangeLength). This is because the filters are run in
_update() and _insert() which reside in Solar_Sql_Model_Record. This also
means that our hooks for _preSave, _preUpdate, etc will not help us as well
and if we were to use these hooks we would return false positives as
mentioned before.

I have also tried using Solar_Sql_Model::fetchAll() and specifying the
columns I want to work with (including the primary key (e.g. 'id'). For some
reason or another, when I save the record, I am thrown back validation
errors which are displayed in my web form. I assume this is because I have
null values for some of the cols such as the password col due to the fact
that I did not pass this col as one of the cols to fetch in fetchAll().

The current work around I have, and dislike, is to call
Solar_Sql_Model_Record::__unset('password') in my controller to remove the
'password' key from the record before the save(). This ensures that the
filter is not run on the password col at save time. The downside is that for
any action I want to update user information and do not want to alter the
password, I have to call __unset().

I have yet to find a work around but I have a proposed solution. It would
entail something along the lines of comparing the data fetched to the data
that is about to be updated. If the data to be updated does not differ from
the data originally fetched, there is no need to run a filter on that data,
or even to update that data all.

I noticed that Tipos has encountered the same hash filter issue I have as I
see a commented line in your model for your hash filter ;-)

Comments, suggestions, questions are more than welcome. I see this as being
a common problem that we need to find a common solution for.

Thank you all,
Raymond Kolbe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman-mail3.webfaction.com/pipermail/solar-talk/attachments/20080101/9624f0f1/attachment.html


More information about the Solar-talk mailing list