Devise allowing all attributes by default in Rails 4 - ruby-on-rails

I'm currently running the following:
Rails 4.0.2
Devise 3.2.2
From the Devise documentation it states that Strong Parameters will block all but the following attributes by default - email, password, password_confirmation, current_password.
I edited the new.html.erb in my registration Devise Views to contain three additional attributes - first_name, last_name, profile_name as shown below.
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :first_name %><br />
<%= f.text_field :first_name %></div>
<div><%= f.label :last_name %><br />
<%= f.text_field :last_name %></div>
<div><%= f.label :profile_name %><br />
<%= f.text_field :profile_name %></div>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
For some reason a user can still register by inputting information in all the fields, even the new fields that I added. Is there a reason my attributes are all being allowed by default?
I'm new to programming and I'm following my first rails tutorial so I'm sure I'm making a completely obvious mistake but I can't figure it out and haven't been able to find the same problem by searching online.
Thank you

Gemfile
gem "strong_parameters"
config/application.rb
config.active_record.whitelist_attributes = false
aplication_controller
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :first_name
end

With strong parameters there is no implicit validation on the client side as to whether or not the fields are allowed, but these fields will not actually be saved to the database until you explicitly permit them in your controller. You should be able to verify that the controller is blocking those fields by watching your server console during the create/update action.

The user could enter, but it's not permitted for mass assignment. The following are from Devise README:
In case you want to permit additional parameters (the lazy way™) you can do with a simple before filter in your ApplicationController:
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :username
end
end
Read more about this on Devise's README, strong parameter section.

Related

Ruby On Rails Devise Register and Login with Username instead of Email

I'm trying add a username field to my register using devise
views/devise/registrations/new/html.erb
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
I got an error: "undefined method `username' for #Usermanagement:0x00007f3db801a8e0"
What did I do wrong? I'm new with ROR so please help me to figure out. Thank you!
in addition to the comment from #hazg, you might find the below link from the devise wiki helpful.
This is a walkthrough on how to add the username to your devise model:
https://github.com/heartcombo/devise/wiki/How-To:-Allow-users-to-sign-in-with-something-other-than-their-email-address
Assuming that you have named your Devise Model a User
Add username field to Devise User Model
$ rails generate migration add_username_to_users name:string
Migration file should look like this
class AddUsernameToUsers < ActiveRecord::Migration
def change
add_column :users, :username, :string
end
end
Migrate the Database
$ rails db:migrate
Generate Devise views
$ rails generate devise:views -v registrations
Update sign up & edit profile form
# views/devise/registrations/new.html.erb
# views/devise/registrations/edit.html.erb
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username, autofocus: true %>
</div>
Override the devise controller
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :email, :password])
devise_parameter_sanitizer.permit(:account_update, keys: [:username, :email, :password, :current_password])
end
end
Add model validations
class User < ApplicationRecord
validates_presence_of :username
# ...
end

devise: sign up with username

I create a username column in database. now I want remove email and then user sign up just by username. For this, I can create username field in sign up page, but again I have to complete email field that server create new user, if else, I get validation error of email field. How can I remove email validation and replace it with personal validation of username? and then user just can sign up with enter username and password?
I have below code to:
users_controller.rb:
def user_params
params.require(:user).permit(:username, :email, :password, :password_confirmation, :remember_me)
end
views/devise/registrations/new.html.erb:
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %></div>
<div><%= f.label :username %><br />
<%= f.email_field :username %></div>
<div><%= f.label :password %> <% if #validatable %><i>(<%= #minimum_password_length %> characters minimum)</i><% end %><br />
<%= f.password_field :password, autocomplete: "off" %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "user/shared/links" %>
If you check the documentation you have a section explaining how to do it here.
Personally I wouldn't remove the email from user settings and stick with the suggested on documentation to create a virtual attribute called login.
If you want to remove completely the email, you'll need to remove it with a migration in order to remove the field from the database table and remove it from the model validation.
Also you need to update your views or partials by replacing email with username. Beware you need to update authentication_keys like it's mentioned on docs (use username instead of login)

Custom sign-up form in Devise not working

I have looked at other answers on here and have yet to find one. I am creating a Rails 4 app that allows users to sign in and create a profile. I am using Devise gem for user authentication.
What I want to do is have the user also type in their name and a description of themselves during the signup process. When submit the form the database will be updated with this info as well. Here is what I have done:
1) I ran a migration to create the new columns, "name" and "description", in the users table
2) I ran rails generate devise:views. This allows me to access devise>views>registrations>new.html.erb where I included the "name" label and field. I just used the other labels and fields as a guide. I now get an error saying name_field method is undefined. Where are the other ones like email_field and password_field defined?
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :name %><br />
<%= f.name_field :name %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
Any help in getting this working I would greatly appreciate.
There's no method on the Rails form object that says name_field. name_field is not a valid HTML form input type. Did you do find and replace? You should change
<%= f.name_field :name %>
to
<%= f.text_field :name %>
UPDATE
Overriding configure_permitted_parameters in app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:name, rest_of_user_attrs) }
# you control which attributes can be updated or used for sign in here
end
end
Here's more information for your perusal https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address
#user2623706 have you configured devise for strong parameters. That may be the problem.

Adding Fields To Devise Sign Up Using Rails 4

To start off, I'm new to rails, so I'm still getting the hang of things.
I'm attempting to add two fields to the Devise sign up page, a first name field and a last name field. I've gone ahead and changed the view and the controller in order to attempt this. They look like this:
Controller:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_devise_permitted_parameters, if: :devise_controller?
protected
def configure_devise_permitted_parameters
registration_params = [:firstName, :lastName, :email, :password, :password_confirmation]
if params[:action] == 'update'
devise_parameter_sanitizer.for(:account_update) {
|u| u.permit(registration_params << :current_password)
}
elsif params[:action] == 'create'
devise_parameter_sanitizer.for(:sign_up) {
|u| u.permit(registration_params)
}
end
end
end
View:
<h2>Sign up</h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :firstName %><br />
<%= f.fName_field :firstName %></div>
<div><%= f.label :lastName %><br />
<%= f.lName_field :lastName %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
However, I get this error when I go to view the page:
undefined method `fName_field' for #<ActionView::Helpers::FormBuilder:0x00000003c89940>
Where must I define those methods? or are they automatically defined somewhere else?
Thanks for any help.
With "f.something" you can just define the type of the field in the form. Try something like
<%= f.text_field :lastName %>
This should work.
You can read about the available types of fields here: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for
create a migration like this to add first name and last name to users table:-
class AddFirstnameAndLastnameToUsers < ActiveRecord::Migration
def change
add_column :users, :firstName, :string
add_column :users, :lastName, :string
end
end
And add this to your view :-
<div><%= f.label :firstName %><br />
<%= f.text_field :firstName%></div>
<div><%= f.label :lastName %><br />
<%= f.text_field :lastName %></div>
You can not do f. to column of the table, you do it on the type of the field.
undefined method `fName_field'
This means you don't have the fName column in your database
If you have access to your DB, you'll see that Devise produces a table with a bunch of columns inside. By default, these columns only include email & password for the user. To add more, you first need to add the column to the database & then you should be able to do what you're doing with it.
There's a good railscast on devise you can see how to do this
I know it's a very common mistake done by a rookie while creating a registration form on the very first time because the devise puts all of the fields like f.email_field,f.password_field etc but these all are valid controls, so the developer gets confuse to type an attribute with _field
The 'fname_field' you used to define your first name is not acceptable as the form controls.
Please verify all of the controls which can be used here
and as per the current scenario, you should go for f.text_field

Devise Registration form on any page

I'm trying to allow users to sign up for the site on my home/landing page.
I've duplicated the devise registration form into my landing page view-
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :first_name %><br />
<%= f.text_field :first_name %></div>
<div><%= f.label :last_name %><br />
<%= f.text_field :last_name %></div>
<div><%= f.label :profile_name %><br />
<%= f.text_field :profile_name %></div>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
<%= render "devise/shared/links" %>
And I've also added the helper methods in my application_controller.rb so that I properly define the resource-
class ApplicationController < ActionController::Base
protect_from_forgery
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
end
However I'm still getting the error undefined local variable or method resource'for #<#:0x007fa816b4b750>`
What am I missing here to properly render a REGISTRATION form on my home landing page?
You need to declare those controller methods as helper methods to access them from the views:
helper_method :resource, :resource_name, :devise_mapping
Just add that line inside your ApplicationController after the methods are defined.
You'll notice that the link you provided actually mentions to put this code in the application helper, not the controller... You can avoid this helper_method declaration if you do it that way.

Resources