I'm currently getting user data from a SAML assertion and creating users in a local DB based on that info:
mapped_role = map_role user_role
user = User.where(email: auth_attrs.single('Email')).first_or_initialize do |u|
u.firstname = auth_attrs.single('First Name')
u.uid = auth_attrs.single('UID')
u.provider = resp.provider
u.role = mapped_role
end
This works well enough, but when the user's details change (for instance, their role changes), that data doesn't get updated in the DB. What I've tried doing is moving the role assignment out of the do
block (on the user
object returned by first_or_initialize
) and then calling a follow-up user.save
, but this results in a pretty red screen informing me that the column 'email' isn't unique. I don't want to be creating a new record here, just updating an existing one. Is there a better pattern to be using here?
Edit: I've tried the various approaches laid out here, but they result in the same SQLite3 error. It seems like I'm missing something there.
Edit2: It looks like this might be due to Devise trying to do something behind the scenes with an email field of its own(?).
I think I would go about it like so
mapped_role = map_role user_role
# find the user or initatiate an new un-persisted user
user = User.find_or_initialize_by(email: auth_attrs.single('Email'))
attributes = {firstname: auth_attrs.single('First Name'),
uid: auth_attrs.single('UID'),
provider: resp.provider,
role: mapped_role}
# attempt to update the above record with the appropriate attributes
# this will set the attributes and fire #save
if user.update(attributes)
# successful
else
# handle validation errors
end
This way there is no need for logical handling of users that are already persisted and new users.