Hiding a model function

I'm still developing my user model, and I've reached a quandary.

I want to keep anyone from being able to do "user.password = 'bob'", but
don't want to break any built in AR magic.

I'm not entirely sure I even know how to do that... and beyond that, I'm
not sure if I do figure out how to do that, how I'm going to actually
set the password (I intend to write a change_password function, but if I
take away the ability to do user.password = 'blah', then I almost
certainly can't do self.password = 'blah' either)...

Try attr_protected http://railsapi.org/attr_protected

-r

In your model class:

def password=(password)
end

That will silently ignore the call to password=. You can have it
raise an error if you want.

"I want to keep anyone from being able to do "user.password = 'bob'", but
don't want to break any built in AR magic."

the question is, who do you need to stop from doing this and why? who
is 'anyone'?

Make the method private:

def change_password(pass)
  self.password = pass
end

private
def password=(password)
  do some stuff
  self.save
end

then you can only call the password= method from within the model and then
use model.change_password(password) to make the password change.

M<><

Alan and Ben beat me to it :slight_smile:

that was the reason i asked why you wanted to 'hide' the method.

another method is to just override the method itself

def password=(password)
  self.password_salt = "some random salt value" # used to validate
password at login
  self.password_hash = encrypted_pw
end

i would argue 'what does it HURT?'.

Curious. What kind of environment are you developing in that you can’t trust other developers to know what’s up and to not try something stupid? It’s not like the regular user can do anything to the model as such.

Jason

Luke Ivers wrote:

Chris Hall wrote:

Alan and Ben beat me to it :slight_smile:

that was the reason i asked why you wanted to 'hide' the method.

another method is to just override the method itself

def password=(password)
  self.password_salt = "some random salt value" # used to validate
password at login
  self.password_hash = encrypted_pw
end

Okay, this has prompted me to ask another question: in all of these, it
generates a new salt every time it generates a new password... is there
a particular reason for this? I understand it would be slightly more
secure... but it seems to me the added security of changing the salt
every time the password changes is basically neglible... if someone has
cracked the original salt, they've probably already hijacked the account
and changed the password themselves.

Don't do that. The salt is there for a reason - it makes creating
comprehensive lookup tables that much harder. If you hardcode the salt,
you make it that much easier for someone to generate a lookup table that
covers _all_ of your passwords. You don't "crack the salt" - the salt
adds complexity to the password.

http://en.wikipedia.org/wiki/Salt_(cryptography) explains it well.

protected "encrypted_password="

will take care of what you need. Since symbols and strings are
relatively the same, this will work fine.

Unfortunately ruby doesn't really give you absolute power over making
sure your developers don't go and blow their brains out. You can make
it really hard for them not to blow their brains out, but eventually
one of them will decide to say, well... why don't I just do...

#TODO: Not hardcode this password
user.instance_eval("@attributes['password'] = \"changeme\")
user.save!

Now I can save the password without that silly evaluation going on.
In such case, I really recommend that you fire your developer. Or
roll back his code, isn't that what revisions were made for?