How to Login a User with Devise

How to programmatically sign in a user through Devise in Rails

It is the proper and standard way to programatically sign a user in. Looking at the devise login code sessions#create you can see they use this method as well.

How to log in/out users with Devise in Rails4 testing

This is from their docs:

"Do not use Devise::TestHelpers in integration tests."

You have to sign in manually. This is an example of a test for a website that does not allow users to get to the root path unless signed in. You can create a method in a support file that signs in the user manually and then call it whenever you want to sign in the user, so that you don't have to use this code every time you need to sign in a user.

require 'test_helper'

class UserFlowsTest < ActionDispatch::IntegrationTest
test "signed in user is redirected to root_path" do
get user_session_path
assert_equal 200, status
@david = User.create(email: "david@mail.com", password: Devise::Encryptor.digest(User, "helloworld"))
post user_session_path, 'user[email]' => @david.email, 'user[password]' => @david.password
follow_redirect!
assert_equal 200, status
assert_equal "/", path
end

test "user is redirected to sign in page when visiting home page" do
get "/"
assert_equal 302, status
follow_redirect!
assert_equal "/users/sign_in", path
assert_equal 200, status
end
end

EDIT: Just in case it's helpful in the future. You can use Warden Test Helpers for integration tests but the way above is a better test. This is a working example:

require 'test_helper'
include Warden::Test::Helpers
class UserFlowsTest < ActionDispatch::IntegrationTest
test "user can see home page after login" do
@david = User.create(email: "david@mail.com", password: Devise::Encryptor.digest(User, "helloworld"))
login_as(@david)
get "/"
assert_equal 200, status # User gets root_path because he loged in
assert_equal "/", path
logout
get "/"
assert_equal 302, status # User is redirected because he loged out
Warden.test_reset! #reset Warden after each example
end
end

Devise - sign in by email OR username

You're sending the login attribute to the db; you need to make it either username or email, which is done with a combination of both a custom attribute & special lookup, as per the docs:

#app/models/user.rb
class User < ActiveRecord::Base
#remove attr_accessor :login (it just makes getter/setter methods which we do manually below)

protected

def login=(login)
@login = login
end

def login
@login || self.username || self.email
end

private

def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions.to_h).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions.to_h).first
end
end
end

--

You've done a great job with the sanitizer etc -- what you're doing is taking a single "login" attribute & making Devise use either login, username or email to find the User record.

At present, the error says users.login cannot be found -- this means your Devise install is looking up login (which isn't in your database), when it should be searching through username and email WITH the login attribute.

The second bit of code (self.find_for_database_authentication) performs a lookup for Devise. If you read the query, it takes the login attribute and sets it to looking up either username or email. This is missing from your implementation and should be added.

After adding, remember to restart your server.


Update

Your attr_accessor should be in your model (yours is in your controller).

All it does is define a setter and getter method for the attribute you define. It's most commonly referred to as a "virtual" attribute, as it's not saved in the database.

I could tell you about setter / getter methods if required, I'll leave it for now to prevent confusion

Devise create user and login on test setup

You can use fixtures to create an admin user in the test database (you probably already have a test/fixtures/users.yml file), and Devise's Test helpers to sign in:

sign_in :user, users(:admin)

If your users are confirmable, remember to set a confirmed_at date.

Check out the Devise wiki article on testing Rails controllers.

Devise - How to trigger a sign_in on page user already has access to

This sounds like you need some controller specific code.

When a user clicks on the link, have the corresponding action do something like this:

    def image_action # Whatever the action name is
if current_user # current user is given to you by devise
# Do stuff that a logged in user would do
else
# redirect to login page
end
end

The idea being that you leave the logic out of the view, and instead either have the controller serve the logged in user the appropriate data / page or have an unauthenticated user redirected to the login page.

current_user is a method given to you by devise that evaluates either to the currently logged in user making the request or nil if the user is not logged in.

If you post your controller code, I'll file out more of my example code, I just didn't want to make it too specific at risk of being confusing.

How to sign in a user using Devise from a Rails console?

Here's one way I was able to do it:

>> ApplicationController.allow_forgery_protection = false
>> app.post('/sign_in', {"user"=>{"login"=>"login", "password"=>"password"}})

Then you can do:

 >> app.get '/some_other_path_that_only_works_if_logged_in'
>> pp app.response.body

Devise user owns account, account has many users

You would do better by having Account as the parent and User as the child like so:

Account has_many Users

So what you could do is in your User model create a callback to check for the presence of an account and create one if it's blank.

before_validation :create_account_if_blank

def create_account_if_blank
if self.account.blank?
ApplicationRecord.transaction do
account = Account.create!(name: self.full_name)
some_other_thing = Something.create!(name: 'test')
end
end
end

Then when you create another user from your "Admin" account, just set the the current account from the controller.

You could even do something like this:

current_account.users.create(your parameters here)

Put the current_account function in your application controller.

The current_account function would look like this:

def current_account
return current_user.account
end


Related Topics



Leave a reply



Submit