Recaptcha only showing up after page refresh - Rails 4 - Devise - devise

I have installed recaptcha according to the gem instructions, however when I view the sign_up page (using Devise), the catcha doesn't appear until I refresh the page.
Looking through other comments, the recommendation is to disable turbolinks (which I am using) by changing the sign_in link to:
<%= link_to "Sign up", new_registration_path, "data-no-turbolink" => true %><br />
I have tried this, but I still don't get the captcha until I do a page refresh.
Relevant code:
Views/devise/registrations/new.html.erb
................
<%= recaptcha_tags %>
................
/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def create
if !verify_recaptcha
flash.delete :recaptcha_error
build_resource
resource.valid?
resource.errors.add(:base, "There was an error with the recaptcha code below. Please re-enter the code.")
clean_up_passwords(resource)
respond_with_navigational(resource) { render_with_scope :new }
else
flash.delete :recaptcha_error
super
end
end
def clean_up_passwords(*args)
# Delete or comment out this method to prevent the password fields from
# repopulating after a failed registration
end
end

Issue was that I needed to still include "class:" in the link:
<%= link_to "Sign up", new_user_registration_path, "data-no-turbolink" => true, class: "btn btn-primary btn-med" %>

Just try in controller this code
def create
if resource.valid? && !verify_recaptcha
clean_up_passwords(resource)
flash.delete :recaptcha_error
elsif !resource.valid? && verify_recaptcha
clean_up_passwords resource
respond_with resource
elsif !resource.valid? && !verify_recaptcha
flash.now[:alert] = "Recaptcha error"
flash.delete :recaptcha_error
clean_up_passwords resource
respond_with resource
end
end
And in your Views/devise/registrations/new.html.erb
<%= recaptcha_tags display: {theme: 'red', tabindex: 5}, ssl: false, noscript: false %>

Related

The error message when trying to login from devise is not showing in a Rails 7.0 application

I have a rails 7.0 application, in my application.html.erb
<body>
<%= yield %>
<div class="signin-container">
<div class="signin-container-inner">
<%- flash.each do |name, msg| -%>
<%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
<%- end -%>
</div>
</div>
</body>
When I visit signin page and add some wrong email or password the error message is not showing.
Since Ruby on Rails 7 uses :turbo_stream, we need to make some modifications to get what you need.
First, we let's add a new parent controller for Devise:
# frozen_string_literal: true
# app/controllers/turbo_devise_controller.rb
class TurboDeviseController < ApplicationController
class Responder < ActionController::Responder
def to_turbo_stream
controller.render(options.merge(formats: :html))
rescue ActionView::MissingTemplate => e
if get?
raise e
elsif has_errors? && default_action
render rendering_options.merge(formats: :html, status: :unprocessable_entity)
else
redirect_to navigation_location
end
end
end
self.responder = Responder
respond_to :html, :turbo_stream
end
Second, we also need to tell Devise to use our new controller and also add a class to handle our errors:
# frozen_string_literal: true
# app/config/initializers/devise.rb
# ! Create custom failure for turbo
class TurboFailureApp < Devise::FailureApp
def respond
if request_format == :turbo_stream
redirect
else
super
end
end
def skip_format?
%w(html turbo_stream */*).include? request_format.to_s
end
end
Devise.setup do |config|
...
config.parent_controller = 'TurboDeviseController'
config.navigational_formats = ['*/*', :html, :turbo_stream]
config.warden do |manager|
manager.failure_app = TurboFailureApp
end
...
end
That's it.
More information about it: GoRails - How to use Devise with Hotwire & Turbo.js
Here is a workaround this issue that occurs when using Rails 7, Hotwire, Turbo, and Devise together. By passing data:{turbo: false} along with each Devise form, it can prevent Turbo from conflicting with the Devise authentication process. This should allow Devise to function properly while still using Hotwire and Turbo in your Rails application.
Here is an example of how you might use data:{turbo: false} on a Devise form:
<%= form_for(resource, as: resource_name, url: session_path(resource_name), data: {turbo: false}) do |f| %>
<%= f.label :email %>
<%= f.email_field :email, autofocus: true %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Log in" %>
<% end %>
In this example, the data: {turbo: false} is being passed as an option to the form_for helper method. This tells Turbo to not apply any of its features to this form, which should prevent any conflicts with Devise's authentication process.

submitting form using remote: true in rails not working

This is my view
<%= form_tag url_for(action: :comt, id: #com.id), remote: true do |f| %>
<textarea name="inst">test</textarea>
<button class="small" id="btn">Submit</button>
Here is my controller:
def comt
id= params[:id]
#com = comment.find id
if #com.update_attribute(:instruction, params[:inst])
redirect_to action: :index
end
end
It is working correctly but i need it using ajax.
If i remove redirect_to it throwing error message. Where i am wrong. Can anyone correct it.

authentication, cant go through login page

im trying create backend under password from database and i cant go through login page :P
My AdminController
class Backend::AdminController < ApplicationController
layout :layout
before_filter :authorize, :except => :login
def authorize
if session[:backend] != true
redirect_to backend_login_path
end
end
private
def layout
if session[:backend] == true
"admin"
else
"login"
end
end
def login
employee = Employee.authenticate(params[:name], params[:password])
if employee
session[:backend] = true
redirect_to backend_root_path, :notice => "Logged in!"
else
flash.now.alert = "Invalid login"
end
end
def logout
session[:backend] = nil
redirect_to backend_login_path, :notice => "Logged out!"
end
end
My Routes
match "backend/login" => "backend/admin#login"
match "backend/logout" => "backend/admin#logout"
My Login page
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %>
<h1>Log in</h1>
<%= form_tag backend_login_path do %>
<p>
<%= label_tag :name %><br />
<%= text_field_tag :name, params[:name] %>
</p>
<p>
<%= label_tag :password %><br />
<%= password_field_tag :password %>
</p>
<p class="button"><%= submit_tag "Log in" %></p>
<% end %>
when i go on url /backend im redirected to /backend/login, thats right
when i enter good login or bad login nothing happened and NO flashes appears thats strange ?
from webserver console output, i see the POST informations go through login method.. i dont know what is wrong ? thank you
edit: when i try go to URL /backend/logout im getting
Unknown action
The action 'logout' could not be found for Backend::AdminController
i really dont understand this :( im begginer
one of the conventions in rails is, that public methods in a controller are considered to be actions.
if you want to write methods for before_filter etc, make them private or protected so that rails will not expose them as actions.
on the flipside, you are not able to define actions as private.

Rails - how do I show an Add Favourite button to users who are not logged in?

I'd like to display an "Add to Favourites" button to users that are not logged in so that they can see that logged in users can add posts (in this case) to their favourites.
Here's the current code:
routes.rb
resources :users do
resources :favourites
end
resources :favourites, only: [:create, :destroy]
posts_helper.rb (I'll move this application_helper once I get it working)
PostsHelper
def new_favourite
if signed_in?
return current_user.favourites.build
else
return Favourite.new
end
end
end
show.html.erb
<%= render :partial => 'shared/favourites/favourite_form', :locals => { :object => #post } %>
_favourite_form.html.erb
<% if signed_in? && current_user.favourited?(object) %>
<%= render partial: 'shared/favourites/unfavourite', locals: { object: object } %>
<% else %>
<%= render partial: 'shared/favourites/favourite', locals: { object: object } %>
<% end %>
_favourite.html.erb
<%= form_for(new_favourite, remote: signed_in?) do |f| %>
<div>
<%= f.hidden_field :object_id, :value => object.id %>
<%= f.hidden_field :object_type, :value => object.class.name.demodulize %>
</div>
<%= button_tag(:type => 'submit', :id => 'add_favourite') do %>
Add to Favourites
<% end %>
<% end %>
I want it to not do an ajax call (ie submit the add favourite form using a page reload) if the user is not signed in so that it will see the user is trying to access a protected page, will redirect them to login and upon success [when it redirects them back to where they were originally trying to go] it will add the favourite.
Can someone advise what I would need to change to make this possible.
EDIT:
Code updated to reflect current state.
After signing in it redirects back to No route matches [GET] "/favourites" because favourites are a nested resource under users.
EDIT 2:
The redirect works pretty much the same as in Rails Tutorial:
Redirect user to sign in page (signed_in_user):
http://ruby.railstutorial.org/book/ruby-on-rails-tutorial#code-correct_user_before_filter
Store location to redirect user back to:
http://ruby.railstutorial.org/book/ruby-on-rails-tutorial#code-friendly_forwarding_code
http://ruby.railstutorial.org/book/ruby-on-rails-tutorial#code-friendly_session_create
The only difference is that on my signin page I use a facebook omniauth link for the user to login but the redirection after logging in still works as expected.
Use a helper method instead of current_user.favourites.build?
<%= form_for(new_favourite, remote: true) do |f| %>
Helper:
PostsHelper
def new_favourite
if signed_in?
return current_user.favourites.build
else
return Favourite.new
end
end
end

Devise Sign in Sign Out link Error

I followed the wiki to create the links but get this error: Granted I am fairly new to Rails and Devise
uninitialized constant ApplicationController::UserSession
Extracted source (around line #1):
1: <% if user_signed_in? %>
2: <li>
3: <%= link_to('Logout', destroy_user_session_path, :method => :delete) %>
4: </li>
Trace of template inclusion: app/views/layouts/_header.html.erb, app/views/layouts/application.html.erb
app/controllers/application_controller.rb:10:in `current_user_session'
app/controllers/application_controller.rb:16:in `current_user'
app/views/devise/menu/_login_items.html.erb:1:in`_app_views_devise_menu__login_items_html_erb__1251633497065791740_2169375180__3843613137737702562'
app/views/layouts/_header.html.erb:13:in `_app_views_layouts__header_html_erb___2695761790912056148_2169430740_3591649723346667383'
app/views/layouts/application.html.erb:10:in `_app_views_layouts_application_html_erb__2958864439808398489_2169528520__269406770402330689'
I had the same problem because I was migrating from authlogic to devise and I forgot to delete the authlogic specific methods in the application controller, like
private
def current_user_session
return #current_user_session if defined?(#current_user_session)
#current_user_session = UserSession.find
end
def current_user
return #current_user if defined?(#current_user)
#current_user = current_user_session && current_user_session.record
end
def require_user
unless current_user
store_location
flash[:notice] = "You must be logged in to access this page"
redirect_to new_user_session_url
return false
end
end
def require_no_user
if current_user
store_location
flash[:notice] = "You must be logged out to access this page"
redirect_to account_url
return false
end
end
def store_location
session[:return_to] = request.request_uri
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
I hope this can help you.
Not sure if this is the problem, but have you tried setting :method => :delete to :method => :get? I would also suggest setting the link_to to button_to since you are trying to "do something" and not necessarily "go somewhere."