Rails - Strong Parameters and attr_accessible - ruby-on-rails

Rails newb, just working on my first app and my first coding experience outside of a little python and bash for sysadmin type work. Using rails 4.1 on C9 and kind of curious why I am experiencing a situation. From what I have read regarding using strong parameters, this replaces the old Rails 3 use of attr_accessible.
I am using devise and setup auth on my app, then wanted to add some custom fields like username and zipcode to be updated via a user profile page. Here is the code that I have to accomplish this. From what I have read the strong parameters should be moved from the model into the controller.
app/controllers/registrations_controller.rb # this inherits the devise::reg
def sign_up_params
params.require(:user).permit(:username, :email, :password, :zipcode, :password_confirmation)
end
def account_update_params
params.require(:user).permit(:username, :email, :password, :zipcode, :password_confirmation, :current_password)
end
However, even after adding this it is still not saving the fields via my /users/edit page without the addition of the following.
app/models/user.rb
attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :zipcode
Once the username and zipcode symbols (not sure of that is the correct term) have been added to the user.rb then the database is populated. The only thing I can think of is the fact that I added the gem 'protected_attributes' awhile back when trying to figure this out. Is this what is forcing me to use the attr_accessible statement in the user.rb?
If there is any additional code that would be useful just ask. Thanks for taking a look, it's much appreciated as I start to understand this.

I guess I should have just attempted this myself before asking here. I removed the gem 'protected_attributes' and commented out the attr_accessible line and restarted rails and viola, it still works. :D

Related

Force required field on second registration step with devise and on-update callback

I have a User model which uses Devise for authentication. My User model has additional attributes like city etc.
On my registration page i only require email and password on user creation. Then i redirect the user to the User edit page to fill up the additional fields.
Validation looks like this:
validates :email, :password, presence: true
validates :city, presence: true, on: :update
So far so good - everything works fine with Rails 5.0.2 - now i upgraded to 5.1.5 and it redirects me straight back to registration page with the message 'city required'.. in the console i can see that the User is created. The thing is - it updates the user on login with last signed in stuff.
It's weird cause it shouldn't work with either of those rails versions.
Is there any better solution to force the user to update some additional fields after registration?
My registrations controller:
class RegistrationsController < Devise::RegistrationsController
private
def after_sign_up_path_for(resource)
edit_user_path
end
end
Your on: update must be within the options for the presence-validation. eg:
validates :city, presence: { on: :update }
However - you could also consider looking into using a form-pattern for each step of your process... which is how a lot of people do multi-stage form validation. Each form represents a stage in the process and has its own set of validations.
Figured out some kind of 'hack' to easily get it working:
validates :city, presence: true, unless: lambda { |u| u.last_sign_in_at_was.nil? }
The _was part is crucial.

has_secure_password, wont create attributes

I am trying to use has_secure_password and bcrypt (3.1.11) on my Rails app.
Here is my setup on Ubuntu:
I installed bcrypt with no issues and have it in my gem file
I have a password_digest:string for my users migrated in the database
I added has_secure_password to my user model
I am getting no errors, however when I go to create a user, it is asking me for a password_digest attribute instead of password and password_confirmation.
why is this? Shouldn't the has_secure_password automatically change the user to need a password and password_confirmation instead of password_digest?
Nope, you don't store the password and password_confirmation, just the password_digest. You never want to store plain text passwords in your db.
When you create a new user you do
User.create(password: 'something', password_confirmation: 'something', ..other fields..)
and then has_secure_password takes care of updating the password_digest in the database.
It's also a good rule to include some validations in your User model.
validates :password_confirmation, presence: true, on: :create
validates :password, confirmation: true
Also don't forget to white list them in your controller
def user_params
params.require(:user).permit(:password, :password_confirmation)
end
User.create(user_params)
You'll probably need to change the form and/or create template manually to contain a password_confirmation field. Look more closely at the has_secure_password docs maybe?

Rails 4 : Jquery token Input is not saving attributes

I have been working with jQuery token input and Rails 4.
Devise gem Application controller
devise_parameter_sanitizer.for(:account_update) { |u| u.permit( :email, :first_name, :last_name,
:password, :password_confirmation, :current_password, :passion_tokens => [] ) }
I want to save users :passion_tokens, but not able to save it. I have mentioned it in controller as per strong parameters.
user.rb
attr_reader :passion_tokens
def passion_tokens= (ids)
self.author_ids = ids.split(",")
end
So, please provide possible way to save the data.
attr_reader does not write to the attributes, which is the probable cause of your attributes not saving. You should use attr_accessor if you want to both read and write or attr_writer if only writing to attribute is required.

Require Nested Params in Controller

I need to know how to require nested params in a Ruby on Rails API. I have my method set up for the param whitelisting as below:
def user_params
params.require(:user).permit(:email, :password, :profile => [:name, :birthdate, :addy])
end
However, that makes profile a permitted param, not a required one. I want profile to be required. It's allowed to have no other nested params (essentially everything nil), but must still be required. How do I accomplish this?
Most likely the "required" portion is going to come from your actual model. So, in this case, go to your user.rb file and add the following.
validates :profile, presence: true
Is that what you're talking about? Usually, you're going to want to allow params in the controller and perform validations and stuff in the actual model file.
If you want to make multiple items required in the controller you can add them like so:
def user_params
params.require(:user).permit(...)
params.require(:profile).permit(...)
end
Rails strong parameters documentation in github

Is there a security risk associated with defining multiple "params" in rails?

I am new to rails and making myauthentication/authorization system since devise was way overkill for what I needed. I realize that since I am not a security expert it will probably have holes. I have tested to the best of my knowledge whether the following would present a security issue, but maybe someone more experienced would be kind enough to give me their two cents :)
Here's the code, it is pretty self explanatory what I'm trying to do:
def user_params
if is_super_user
params.require(:user).permit(:firstname, :lastname, :email, :password, :password_confirmation, :role_id)
else
params.require(:user).permit(:firstname, :lastname, :email, :password, :password_confirmation)
end
end
So a regular user should not be able to alter permissions levels whereas a super user can. Is this okay to do? Is there a better solution?

Resources