How to invoke devise authentication from a different controller? - ruby-on-rails

I am building a movies website. I would like the home page (views/movies/index.html.erb) to display a list of all movies even to visitors who are not signed in. And I would like to provide a login link on the home page which when clicked should invoke the authentication system of devise gem. How do I achieve this?
I provide this link on the home page (views/movies/index.html.erb)
<%= link_to 'Log in', login_path, :class => "btn btn-primary" %>
I have this in my routes.rb file:
get 'login', to: 'devise#new', as: 'login'
I have provided this dummy method in movies_controller.rb
def login
end
This is the new session (login) code generated by devise in /views/devise/sessions/new.html.erb
<header>
<h1>
Log in
</h1>
</header>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<%= f.label :email %> <%= f.email_field :email, autofocus: true, class: "form-control" %>
<%= f.label :password %> <%= f.password_field :password, autocomplete: "off", class: "form-control" %>
<% if devise_mapping.rememberable? -%>
<%= f.check_box :remember_me %> Remember Me
<% end -%> <%= f.submit "Log in", class: "btn btn-primary btn-lg" %>
<% end %>
<%= render "devise/shared/links" %>
If I somehow invoke /views/devise/sessions/new.html.erb, would that solve my problem?
If yes, then how can I invoke this erb from movies_controller?
If no, then how else can I solve my login problem?

Related

Rails/Devise. Include captcha response param within sign_in process

Without making a custom Sessions controller that inherits from the hidden devise controller, I want to figure out a way of adding the parameter, "g-recaptcha-response" to be included in the authenticating process from the default devise view.
Here's my view with the recaptcha figure included. When I click on it I do get a response when my app calls the SessionController#create method. I'm trying to figure out how to make this process detect that the captcha form has been clicked and authenticates the user logging in because of it.
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<% if devise_mapping.rememberable? -%>
<div class="field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end -%>
<div class="g-recaptcha" data-sitekey="6LeeL5gUAAAAADbq0vt4d9biAs8oegkPx9ttUkKb"></div>
<div class="actions">
<%= f.submit "Log in" %>
</div>
<% end %>
<%= link_to 'Sign Up', new_user_registration_path %>
In essence, if a bot were to attempt automatically signing in repeatedly, the devise controller would see that the captcha was not clicked and stops them from trying to log in.

Navbar login form in a Rails web app (with Bootstrap)

I'm making a Rails web app with the limited knowledge I have - mostly from the Hartl Rails Tutorial. I'm also using Bootstrap.
I decided it would be good to have a dropdown login form in the navbar, in addition to the form at '/login'. The form looks nice enough, but I can't get it to work.
Here is my current code for my working, '/login' form:
<%= form_for(:session, url: login_path) do |f| %>
<div class="form-group">
<%= f.label :username %>
<%= f.email_field :username, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<%= f.submit "Log in", class: "btn btn-primary center-block" %>
<% end %>
Here's my code for the non-working navbar form:
<%= form_for(:session, url: login_path, method: :post,
html: { role: "form", id: "navbar-login" }) do |f| %>
<div class="form-group-sm">
<%= f.label :username %>
<%= f.text_field :username, class: 'form-control',
name: 'username', placeholder: 'Username' %>
</div>
<div class="form-group-sm">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control',
id: 'password', name: 'password',
placeholder: 'Password' %>
<%= link_to "Forgot password?", '#' %>
</div>
<%= f.submit "Log in", class: "center-block" %>
<% end %>
And here's my sessions_controller.rb create method:
def create
user = User.find_by(username: params[:session][:username])
if user && user.authenticate(params[:session][:password])
log_in user
redirect_to user
else
flash.now[:danger] = "That email and password combination isn't
correct."
render 'new'
end
end
The error I get when submitting the form is as follows:
NoMethodError in SessionsController#create
undefined method `[]' for nil:NilClass
The error also points to this line of the create method:
user = User.find_by(username: params[:session][:username])
I guess the answer is pretty simple, but I can't quite figure it out. I'm sure it must be either form_for or the create method that isn't working.
Thanks in advance for any help.
Remove the name attribute from every field in the form.
Rails handles it for you and the way you are naming it is not creating the param that you expect.

I can't implement un-clickable text_fields in Rails

I have an application that I have been working on and have everything wired up to my liking but was wondering if this is possible:
I am displaying a users username in an edit.html.erb template. I want it to display the users username inside of the <%= f.text_field :username, :class=> "uneditable-input" %>. I am using Bootstrap and in the documentation, it states to add a class of uneditable-input, when I hove rover the username text field, it shows a little white stop sign but I am still able to click on the field and edit it. Any help?
<%= render 'shared_partials/errors', errors_object: #user %>
<div class="page-header">
<h2> Edit Your Profile<small> - <%= #user.username %></h2></small>
</div>
<div class="well">
<%= form_for #user do |f| %>
<%= f.label :username %>
<%= f.text_field :username, :class=> "uneditable-input" %>
<%= f.label :password %>
<%= f.password_field :password, :class=> "input", :placeholder=>"Password goes here" %><br/>
<%= f.submit "Update Changes", class: 'btn btn-primary' %>
<% end %>
</div>
Make the field disabled.
<%= f.text_field :username, :class=> "uneditable-input", :disabled => true %>
While submitting the form, browser will not send the value for the field username and thats correct, why it should be sent if it is un-editable.

redirect to a page after sign in , in ruby on rails

I am trying to automatically redirect my user to skip the login page if he or she has an active session
my current code, which prompts the user with another page with a link in it. I tried to do redirect_to but ruby does not work with that method.
Any suggestions?
<% if signed_in? %>
<%= link_to "Users", 'users/show' %>
<% else %>
<%= form_for(:session, url: sessions_path) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<br>
<%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
In your login page's controller (maybe session#new) you can check for the user's session like
if current_user or cookies[:session]
so within your new action
class SessionsController < ApplicationController
def new
redirect_to(root_url, alert: "already logged in") if current_user
end
end

trouble converting from form_for to form_tag

How do I convert this to form_tag? This code is basically from RoR Tutorial by Michael Hartl Chapter 8 Exercise 1
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(:session, url: sessions_path) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
I tried something like this
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<% form_tag sessions_path, methods=> :post do %>
<%= label_tag 'email' %><br />
<%= text_field_tag :email, params[:email], :placeholder => "Email" %>
<%= label_tag 'password' %><br />
<%= password_field_tag :password %>
<%= submit_tag 'Sign in' %>
<% end -%>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
But its not displaying the form at all.
Thanks
You need to add an equal sign:
<%= form_tag sessions_path, methods=> :post do %>
However, I wonder why you want to switch to form_tag. form_for has many advantages in my opinion e.g. the form builder.
I am also trying to convert to the form_tag.
Correct Syntax
<%= form_tag sessions_path, :method => 'post' do %>
Incorrect Syntax
<% form_tag sessions_path, methods=> :post do %>
You need to add an '=' to the opening embed tag, change methods to :method, and :post to 'post'
The reasons for using form_for vs form_tag, are discussed in another stack overflow thread.
Another change that needs to be made is in the sessions_controller.rb. The hash passed back wont be recognized by the controller, as it is set up to accept a hash from form_for method. You must remove the first [:session] hash in two lines. Your sessions_controller.rb should look like this,
def create
user = User.find_by(email: params[:email].downcase)
if user && user.authenticate(params[:password])
sign_in user
redirect_to user
else
flash.now[:error] = 'Invalid email/password combination'
render 'new'
end
end
The next will be the code for the Tutorial (Michael Hartl 3.2) Chapter 8 . Exercise 1
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<%= form_tag sessions_path, :method => 'post' do %>
<%= label_tag 'email', 'Email' %>
<%= text_field_tag :email, params[:email], :placeholder => "Email" %>
<%= label_tag 'password', 'Password' %>
<%= password_field_tag :password %>
<br>
<%= submit_tag "Sign In" , :class=> "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>

Resources