how to call devise methods - ruby-on-rails

i create controller:
class SigninController < ApplicationController
def index
end
def create
#user = User.find_by_email(params[:user][:email])
if #user
....
sign_in(:user, #user)
else
#user = User.new(params...)
#user.save
...
end
end
end
Correctly i call sign_in method?
signin/index.html.erb:
<h2>Sign in</h2>
<%= form_for(User.new, :as => :user, :url => "signin") do |f| %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<br>
<div><%= f.submit "Sign in" %></div>
<% end %>
How to call devise sign_in and sign_up methods of devise?

Try this in app/controllers/application_controller.rb:
class ApplicationController < ActionController::Base
def after_create_path_for(resource)
sign_in(:user, resource)
end
end
That's just kind of a guess. I don't know if it will work.

You may but in most cases you should not create custom controller to sign in / out user. Devise has sessions_controller which implements this functionality for you. View devise documentation and wiki, it has plenty of documentation. Also you can found out there how to customise views and controller behaviour.
Update
If need to place both forms (login and registrations) on one view you can customise devise view. Form actions may point to different standard controllers. I suggest to use users/registrations/new form for base form and add uses/sessions/new form to it.

Related

Is it safe to edit user based on devise current_user helper?

I'm using Devise, Omniauth-twitter and Omniauth-facebook for my rails app authentication and i had to make my own controller for editing user parameters without needing a password for users with providers like facebook and twitter.
And instead of routing the user to his profile by his user id, I used the devise helper current_user to show and edit the current_user parameters
My question is.. is it safe to do that ?
I'm a beginner.. so when something is done that easy i worry about security vulnerabilities. Here's my code.
profile_controller.rb
class ProfileController < ApplicationController
before_action :authenticate_user!
def show
#user = current_user
end
def edit
#profile = current_user
end
def update
#profile = current_user
if #profile.update(profile_params)
redirect_to profile_path(#profile)
else
render 'edit'
end
end
private
def profile_params
params.require(:user).permit(:username,:first_name,:last_name,:gender)
end
end
routes.rb
get'profile' => 'profile#show'
get'profile/edit' => 'profile#edit'
patch'profile/edit' => 'profile#update'
edit.html.erb
<%= form_for #profile, url: {action: "edit"} do |f| %>
<%= f.text_field :username, autofocus: true %>
<%= f.text_field :first_name, autofocus: true %>
<%= f.text_field :last_name, autofocus: true %>
<%= f.text_field :gender, autofocus: true %>
<%= f.submit "Sign up" %>
<% end %>
Well if you are using Devise you could make user of their existing views rather than, you trying to implement them on your own. But, I don't see any security threats with your current approach it's just that it is a waste of time.
Take a look at the devise documentation and check the Configuring Views section,
https://github.com/plataformatec/devise

Using form_for with "becomes" loses child association

When building out a form that handles STI, if I use becomes to transform the object to its parent class, I lose the ability to use nested fields with it.
I have two models
class Login < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :login
accepts_nested_attributes_for :login
end
I also have a few subclasses of User.
class Consumer < User
end
class Admin < User
end
class Agent < User
end
Initially I had problems with the routing, since Rails would assume that I wanted a route specific to the current class rather than the parent class, so I used #user.becomes(User), which is apparently the way to handle that. For the most part it works fine, however this causes #user.login to disappear.
Controller
class Admin::UsersController < AdminController
load_and_authorize_resource
before_filter :authenticate_user!
def index
render 'index'
end
def new
#user = User.new
#user.build_login
render 'new'
end
def create
#user = User.new(user_params)
if #user.save
flash[:notice] = "Account confirmation instructions sent to #{#user.login.email}"
redirect_to new_user_path
else
flash.now[:error] = #user.errors.full_messages.to_sentence
# At this point, I can confirm that #user.login still exists...
render 'new'
end
end
private
def user_params
params.require(:user).permit(
:type,
:dealership_id,
login_attributes: [
:email
])
end
end
Here's the most relevant form view bit
<%= simple_form_for(#user.becomes(User), html: {class: "user-form"}) do |f| %>
<%= f.simple_fields_for :login do |l| %>
<div class="field">
<%= l.label :email %><br />
<%= l.email_field :email %>
</div>
<% end %>
<div class="field">
<%= f.label :type %>
<%= f.select :type, options_for_select(current_user.types_can_create), include_blank: "- Select -", class: "form-control", id: "select_type" %>
</div>
<div class="actions">
<%= f.submit "Register" %>
</div>
<% end %>
The text field for :email doesn't display because #user.login is now nil. Is this expected behavior when using becomes?
Having only used becomes once before, I can only attest to my scant experience -- whenever you use it, it essentially invokes a new instance of the class.
I'm not sure as to the specifics, but the bottom line is that I would surmise that your #user.becomes(User) is overriding #user.build_login...
Returns an instance of the specified klass with the attributes of the current record.
--
In your case, I would set the path explicitly (as you're using User anyway):
<%= simple_form_for #user, url: user_path, method: :post html: {class: "user-form"} do |f| %>
In Rails 5, this can be solved with
<%= form_with scope: :user,
model: #user,
url: #user.id ? user_path(user) : users_path,
local: true do |f| %>
...
...
<% end %>
The previous code instructs the FormBuilder to fill in the fields with the #user attributes, but it also instructs it to submit to the main route (not the inherited ones) and, with scope:, it also instructs it to name the fields using the User class name, not the child class names.

Ruby app using devise for authentication

I am building a simple app that allows members to create a trip. Only one trip. I wanted to get some practice using the devise gem so that setting up the application with sign in, sign out, etc is easy and efficient, but I need some help. Right now I have two models: member & trip, neither of which have a controller.
This is my sign up form and when I click submit, somehow a member is created in the database even without a member controller? How do I redirect this to a different page after submit is pressed?
I'm just a little confused on what I should be adding since devise is doing a lot of the work behind the scenes.
<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, autocomplete: "off" %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
You create a controller to do this.
class UserController < Application::Base
def new
#user = User.new
end
def create
#user = User.new(email: params[:email], password: params[:password], password_confirmation: params[:password_confirmation])
if #user.save
redirect_to <page you want to redirect to>
else
render new
end
end
The user(or in you case member) controller simply talking resides in devise gem internals.
To redirect a user to user/home you may define user_root route in your routes.rb file in this way:
get 'user/home', as: 'user_root'
Read more here.
Devise offers some macros that you can override to choose what paths you want to redirect to.
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
'/an/example/path'
end
end
Source
EDIT:
Create a file in your controller folder called registrations_controller.rb. Put this code into that file.
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
'/an/example/path'
end
end
Replace /an/example/path with whatever path you want to redirect to after someone signs up. Then modify your config/routes.rb to point to that controller by adding this line:
devise_for :members, :controllers => { :registrations => "registrations" }
Then, you may need to edit your config/application.rb by adding this line
config.paths['app/views'] << "app/views/devise"
If you encounter a "MissingTemplate" error.

I am using Devise, the password change is redirecting to home page, how to keep it on /users/edit?

I am using devise and the views file is /devise/registrations/edit.html.erb (I have not made any changes to it):
<div><%= f.label :password %>
<%= f.password_field :password, :autocomplete => "off" %></div>
<div><%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %></div>
<% if f.object.encrypted_password.present? %>
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></div>
<% end %>
<div><%= f.submit "Update" %></div>
When the user changes their password, they are getting redirected to root_url (homepage). I want to keep them at the change password page, which is /users/edit. How can I do it?
EDIT - I do have registration_controller with edit method, what should I add in it ?
The update action in PasswordsController calls a protected method named after_resetting_password_path_for.
The method just calls after_sign_in_path_for so I think it should be safe to subclass PasswordsController and override this method.
It looks like there's is already a test for whent this method is overridden so it looks like it's definitely supported.
First, OP have problem about redirect after change password, change password in devise is in the RegistrationsController, while PasswordsController for "Reset Password". FYI #amesee's answer for redirect after reset password. Change password and reset password are differents
How To: Customize the redirect after a user edits their profile and see after_update_path_for(resource)
You should add after_update_path_for(resource) method on your registrations_controller.rb looks like :
class RegistrationsController < Devise::RegistrationsController
protected
def after_update_path_for(resource)
root_path
end
end
If you have different model for User and Admin, you need this:
routes.rb
devise_for :admins, controllers: {registrations: 'admins/registrations'}, defaults: { format: 'html' }
app/controllers/admins/registration_controller.rb
class Admins::RegistrationsController < Devise::RegistrationsController
def after_update_path_for(resource)
after_change_password_path # change this
end
end

Rails 3 - Devise Gem - How to Manage Users through CRUD interface

Devise gem is used for authentication. I need to have a user index and show view. Found this how to at the devise wiki, however played around, can not make it work.
Devise - How To: Manage users through a CRUD interface
Method 1: Remember to remove the :registerable module from the Devise model (in my case it was the User model) Make sure to put your map.resources :users below the map.devise_for :users route (devise_for :users and resources :users for Rails 3).
Method 2: devise_for :users, :path_prefix => ā€˜dā€™ resources :users to isolate the devise logic from your crud user controlle
My question:
1. if you remove registerable in the model, then how does devise work for user?
2. If you done this, can you provide a sample?
Thanks in advance
The following worked for me.
users_controller.rb
class UsersController < ApplicationController
...
def create
#user = User.new(params[:user])
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
respond_to do |format|
if #user.save
format.html { redirect_to users_path, notice: 'User was successfully created.' }
else
format.html { render action: "new" }
end
end
end
...
end
routes.rb
...
devise_for :users, :path_prefix => 'd'
resources :users
...
I hope this can help you.
Regards,
Giacomo
By placing the appropriate new.html.erb, edit.html.erb, _form.html.erb etc files in the User Views folder, adding/editing/deleting Users should work no differently as any other CRUD, as Devise's User is another model like any. I won't post the new or edit erbs (simple enough, and a scaffold can show you the rest), but an example of my User _form.html.erb...
<%= form_for(#user) do |f| %>
<%= render :partial => 'shared/errors', :locals => { :content => #user } %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
In mine, I think I left :registerable in and I'm still able to administer and update users via the CRUD. If you leave it out, then users can't register themselves, but you can still add and edit users yourself (would protect the Users controller with load_and_authorize_resource to keep regular users out, of course).

Resources