Rails devise plugin customization - ruby-on-rails

In my current Ruby on Rails project, the devise plugin has been used for authentication. To change the password, I added the devise plugin's passwords/edit.html.erb file into the user directory in my project. Everything's working fine except the error messages are not showing.
This is my current update_password method
def update_password
#user = User.find(current_user.id)
if #user.update_with_password(params[:user])
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
I've mentioned the require validation in the user model as follows
validates_presence_of :name, :primary_locale, :current_password, :password, :password_confirmation
This is my edit form code:
<div id="loginForm" class="editPwFormHeight">
<div id="loginHeader"><h3><%= image_tag("wif_small.png"); %></h3></div>
<div id="loginContent">
<%= form_for(#user, :url => { :action => "update_password", :locale => params[:locale] }, :method => "post") do |f| %>
<%= f.hidden_field :reset_password_token %>
<p><%= f.password_field :current_password, :class => "login_txt", :placeholder => I18n.t('wi.common.enterCurrentPw'), :autocomplete => "off" %></p>
<p><%= f.password_field :password, :class => "login_txt", :placeholder => I18n.t('wif.common.newPw'), :autocomplete => "off" %></p>
<p><%= f.password_field :password_confirmation, :class => "login_txt", :placeholder => I18n.t('wif.common.confirmPw'), :autocomplete => "off" %></p>
<p>
<input id="user_submit" name="commit" type="submit" value="<%= I18n.t('wif.common.updatePw') %>" class="login_btn" />
<input id="user_cancel" name="commit" type="button" value="<%= I18n.t('wif.common.cancel') %>" class="login_btn" />
</p>
<% end %>
</div>
</div>
Anyone can help me to solve this issue. I wanted to show the error message if the user has not typed the current password, or any other error which are currently supporting by the devise

You need to add the following line to your template:
<%= devise_error_messages! %>
You can customise the messages themselves by editing Devise's translation files, e.g. config/locales/devise.en.yml
If you're not using devise's built-in controllers, then you will need to register the DeviseHelper module as a helper in your controller using the helper method.

Related

How to signup in two different pages with devise

I used devise inthe login system.I want create two new html under the registrations, which is two different roles' pages. And I want to go to that page by choosing roles in registrations/new, which is the original signup file. What should I do next?
my files order in the view/user/registrations: enter image description here.
edit.html.erb
new.html.erb
new_librarian.html.erb
new_student.html.erb
I want to signup in the new two pages through registrations/new
<!-- what i changed in the registrations/new -->
<h2>Sign up</h2>
<p>Sign up as a Student<%= link_to 'Student', users_registrations_new_student_path, :method => 'get' %></p>
<p>Sign up as a Librarian<%= link_to 'Librarian', users_registrations_new_librarian_path, :method => 'get'%></p>
<!-- what is in the registrations/new_student -->
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", adminv: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, 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="field">
<%= f.label :select_role %><br />
<%= f.collection_select :role, User::ROLES, :to_s, :humanize %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
<!-- what i changed in the routes.rb -->
get 'users/registrations/new_librarian'
get 'users/registrations/new_student'
Could not find devise mapping for path "/users/registrations/new_student". This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example: devise_scope :user do get "/some/route" => "some_devise_controller" end
2) You are testing a Devise controller bypassing the router. If so, you can explicitly tell Devise which mapping to use: #request.env["devise.mapping"] = Devise.mappings[:user]
You can achieve this by overriding the devise registration controller. In your overrided registration controller, in the new method once the user is saved,
#app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
if #user.save!
if #user.role == "librarian"
redirect_to librarian_profile_path
elsif #user.role == "student"
redirect_to student_profile_path
end
end
end
end
You can define librarian_profile_path and student_profile_path in your routes
#app/config/routes.rb
get 'librarian/new' => 'librarian_profile#new', :as => 'librarian_profile'
get 'student/new' => 'student_profile#new', :as => 'student_profile'

reading parameters from create method

I have a ruby on rails project that is using the devise gem for authentication. I'm trying to use a captcha form in the sign up page to prevent bots from creating thousands of dummy logins
I'm not interested in using the recaptcha gem that works with devise as I haven't had any luck setting it up correctly.
I trying to set it up using this as a reference https://recaptchainrubyonrails.blogspot.com/
Here's my sign up page
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url:
registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, 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: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="g-recaptcha" data
sitekey="6LeeL5gUAAAAADbq0vt4d9biAs8oegkPx9ttUkKb"></div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<br>
I do have my routes file point to a separate registrations controller instead of the one created within the devise registrations
devise_for :users, path: '', path_names: { sign_in: 'login', sign_out: 'logout' }, :controllers => {:registrations => "registrations"}
I can create a user regardless if I click on the captcha form. When I do click on it I get the parameter, g-recaptcha-response, in the create method that has a long text string such as
"g-recaptcha-response"=>"1234567890abcdefghi..."
I tried a create method that would look at that parameter and see if it is not nil. When it is nil I would like to back one page to the sign up page.
class RegistrationsController < Devise::RegistrationsController
def create
if not params[:g-recaptcha-response].present?
redirect_to :back
end
end
end
I can't even get to the parameter as it errors out saying
undefined local variable or method `recaptcha' for #<RegistrationsController:0x7219e5a0> Did you mean? catch"
I'm trying to capture this parameter, look at the value of g-recaptcha-response and somehow cancel the creation of a user if the response was nil or empty string
Alrighty, this is what I figured out that worked. Thanks to everyone who helped
#response = params[:"g-recaptcha-response"]
if #response == nil
flash[:notice] = "Please click on captcha form!"
redirect_back(fallback_location: new_user_registration_path)
else
flash[:notice] = "You signed up successfully!"
redirect_to root_path
end
Use 'g-recaptcha-response' instead of :g-recaptcha-response. You need to use string syntax because you cannot use - in symbol naming

<%= current_user.role %> evaluates to nothing in Rails 4

I'm making a Rails app and am trying to have the user's role displayed on a view. The code I am using for this is:
<%= current_user.role %>
Which does not evaluate to anything.
I am using devise for user registrations and my registration view is as follows:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="login-field">
<%= f.email_field :email, :placeholder => "Email" %>
</div>
<div class="login-field">
<%= f.password_field :password, autocomplete: "off", :placeholder => "Password (8 character min)" %>
</div>
<div class="login-field">
<%= f.text_field :firstname, :placeholder => "First Name" %>
</div>
<div class="login-field">
<%= f.text_field :lastname, :placeholder => "Last Name" %>
</div>
<div class="login-field">
<%= f.text_field :phone, :placeholder => "Phone Number" %>
</div>
<%= f.select(:role, ['Role 1', 'Role 2', 'Both']) %>
<br>
<div><%= f.submit "Signup" , :class => "btn btn-success btn-lg" %></div>
<% end %>
<%= render "devise/shared/links" %>
I have a feeling that I am doing something wrong in the form submission but cannot figure out what it is. Any help is appreciated
You can put this at the top of your create action:
return render text: params.inspect # get what the form sended
and or
return render text: create_params # get what the values you permitted
This way you will get what the data your from sended and if it is what you expected.
You should override the sign_up_params in the Devise registration. Once you've created your RegistrationsController that inherits from Devise::RegistrationsController, you can override the sign_up_params:
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:first_name, :last_name, :email, :phone, :role ... any other attributes)
end
end
You would also need to change you routes.rb to point to the newly created controller:
devise_for :users, controllers: {registrations: 'registrations'}

Case insensitive omniauth-identity email login

By default the intridea / omniauth-identity rails gem uses email to login and they are case sensitive. How do I make the login email case insensitive? Adding ":case_sensitive => false" to the model as seen below does not work.
#models/identity.rb
class Identity < OmniAuth::Identity::Models::ActiveRecord
attr_accessible :email, :name, :password, :password_confirmation
validates_presence_of :name
validates_uniqueness_of :email, :case_sensitive => false
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
end
For example, even with the model above if you signed up with "bob#aol.com" and then tried to login with "BOB#aol.com" the login would produce an OMNIAUTH::ERROR of invalid credentials.
Any suggestions?
Ok, so I thought user ForgetTheNorm had the solution, but it turns out modifying the locate_conditions breaks sign up. The solution is actually much simpler than I originally thought. Downcase the auth-key BEFORE it is submitted with the form. This is true of everywhere you use the key. For instance, to login or sign up.
#login-form
<%= form_tag('/auth/identity/callback', :method => 'post', :id => 'actual-login-form') do %>
<div class="field">
<%= label_tag :auth_key, 'Email' %>
<br />
<%= text_field_tag :auth_key, nil, :class => 'user-auth-field user-auth-key' %>
</div>
<div class="field">
<%= label_tag :password %>
<br />
<%= password_field_tag :password, nil, :class => 'user-auth-field' %>
</div>
<div class="actions">
<%= submit_tag 'Sign in', :class => 'btn-default', :id => 'modal-sign-in' %>
</div>
<% end %>
#signup-form
<%= form_tag('/auth/identity/register', :method => 'post', :id => 'actual-signup-form') do %>
<%= label_tag(nil, 'Choose your username') %>
<%= text_field_tag 'name', nil, :class => 'signup-form-input', :tabindex => '1' %>
<%= label_tag(:email, 'Your current email address') %>
<%= text_field_tag 'email', nil, :class => 'signup-form-input user-auth-key', :tabindex => '2' %>
<%= label_tag(:password, 'Create a password') %>
<input type="password" name="password" id="password" class="signup-form-input" tabindex="3" />
<%= label_tag(:password2, 'Confirm your password') %>
<input type="password" name="password_confirmation" id="password_confirmation" class="signup-form-input" tabindex="4" />
<%= submit_tag('Sign Up for Pholder', :id => 'signup-submit', :tabindex => '5') %>
<% end %>
Relevant jQuery/JS:
$('#actual-login-form, #actual-signup-form').on('submit', function(){
//lower case auth key (email addresses) for all user validation
$(this).find('.user-auth-key').val( $(this).find('.user-auth-key').val().toLowerCase() )
})
You can find solutions in
https://github.com/intridea/omniauth-identity/issues/22
For the sake of clarity...
#config/initializers/omniauth.rb
provider :identity, locate_conditions: lambda { |req|
{ model.auth_key => req['auth_key'].downcase }
}
As ujeezy noted above, the omniauth-identity gem on Rubygems does not
support this feature, this is still true. Make sure your gemfile is as
he stated:
#Gemfile
gem 'omniauth-identity', git: 'https://github.com/intridea/omniauth-identity.git'

How i can change password of a user with custom method using Devise

I am using rails 3 with gem devise.Devise has built in method for change password.But i want
that admin can reset password of any user and how i can do it please help..
You can define custom method and also define routes for it
<%= form_for(:user, :url => {:controller => '/administrator', :action => 'change_password',:id => #user.id}, :html => {:id => 'admin_update_form',:method => :put}) do |f| %>
<div class="change-pass">
<h2>Change Passwords</h2>
<div class="pass-detail">
<div class="username-btn">
<label>Passwords</label>
<%= f.password_field :password, :class=> 'fields' %>
</div>
<div class="username-btn" style="margin-bottom:40px;">
<label>Confirm Passwords</label>
<%= f.password_field :password_confirmation, :class=> 'fields' %>
</div>
<%=hidden_field_tag 'user_ids',:id => 'user_ids' %>
<div class="username-btn_button">
<%= f.submit 'change password', :id => 'password_btn' ,:class => 'reg-findjob'%>
</div>
</div>
</div>
In controller code
def change_password
#user = User.find(params[:id])
if #user.update_attributes(:password => params[:user][:password], :password_confirmation => params[:user][:password_confirmation])
flash[:notice] = 'Password was changed successfully.'
render :text => 'ok'
else
flash[:error]=[]
#user.errors.full_messages.each do |error|
flash[:error] << error
end
end
In controller find user and update its password attribute.I am sending user id with form
whose password is to changed or you can do it according your requirement.

Resources