Prevent multiple sessions accros model in devise - ruby-on-rails

I'm on rails 6.0.3 and devise 4.7.3
I have 2 devise models in my rails application. User and Producer
On localhost:3000/users/sign_in, I can create a session with an user.
On localhost:3000/producers/sign_in, I can create a session with an producer.
I was suprised to have two parallels sesssions.
In the situtation, I have acces in the same time to a current_user and a current_producer
I want to prevent this, and if you sign in with a model, it sign out automatically with the other model.
Thanks for advices.

Finaly I found.
I overwrite the user controller.
# app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
def create
super
sign_out :producer
end
end
dont forget to config routes.rbto use this controller:
# config/routes.rb
Rails.application.routes.draw do
# ...
devise_for :users, controllers: {
sessions: 'users/sessions'
}
# ...
end
I did the same thing for producer.

Related

How to differentiate a rails / devise login if it is made by providing password or via cookie?

It seems the most close method is to hook the devise model User to override after_database_authentication method.
But within that model method I was unable to send a flag to the controller which handles the root route. (Somehow current_user could not reach atr_accessor enabled parameter).
So wrapping up, what is the most rails way to differentiate devise authentication, if it is made by providing a password or if it is made by a cookie?
In the rails MVC model the model is not session aware. Your User model thus does and should not know if there is signed in user.
If you want to differentiate from when the user is redirected from the sign in vs other hits on the root path you can set a value in the session:
# routes.rb
devise_for :users, controllers: { sessions: 'sessions' }
# app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController
def create
super do
session[:just_signed_in] = true
end
end
end
# this would be whatever controller you have that handles the route path
class HomeController
after_action :cleanup!
def index
if session[:just_signed_in]
# ...
else
# ...
end
end
private
def cleanup!
session.delete(:just_signed_in)
end
end
Another way to do this is by adding a query param to the redirect path after sign in.

Override create method from SessionController from Devise

I'm working on an api rest application in Rails (using devise) and when an user registers, a token is stored in the database. When the user sign in I have to return a JSON with this token. Any ideas how can I override create method from SessionController from Devise?
First you have to register your new controller, in routes.rb file
devise_for :users, :controllers => {sessions: 'sessions'}
Then you add this controller inside your app/controllers folder, as
app/controllers/sessions_controller.rb and define it as.
class SessionsController < Devise::SessionsController
def create
# put your logic here
# if you want to keep functionality just use
# super
end
end

How to record the IP address a user signed up with using Devise and Ruby on Rails?

I tried the following:
In user.rb:
before_create :record_sign_up_ip
protected
def record_sign_up_ip
self.sign_up_ip = current_sign_in_ip
end
Unfortunately, although current_sign_in_ip has my correct local ip of 127.0.0.1, sign_up_ip remains as nil. How can I easily get the IP of someone signing up? Normally I would put this in the create controller, but with Devise, there is no controller for User.
Override the controller used by Devise as noted at Override devise registrations controller
As modified from that post, create app/controllers/users/registrations_controller.rb:
# app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
def create
params['user']['sign_up_ip'] = request.env['REMOTE_ADDR']
super
end
end
Also modified from that post, to use that controller:
# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "users/registrations"}
You also need to make sign_up_up accessible (for Rails 3):
# app/models/user.rb
attr_accessible :sign_up_ip
In your user model,
def init
self.sign_up_ip = current_sign_in_ip
end

Ruby on Rails Devise code after login

I have an RoR app using Devise for logins. There is some code that is executed when a new User record is created, by being put in the user.rb file as an after_create call/macro/whatever. I need to make this code run after each login, instead of running on new user creation.
With some Googling, it seems that one option is to place Warden callbacks in the devise.rb code. My questions are:
Is this right, and/or is there a better way to do this?
If this is the right approach ...
Should the Warden::Manager... method defs go in devise.rb inside of Devise.setup, or after it?
Is after_authentication the callback I should use? I'm just checking to see if a directory based on the user's name exists, and if not, creating it.
Just subclass Devise's sessions controller and put your custom behaviour there:
# config/routes.rb
devise_for :users, :controllers => { :sessions => "custom_sessions" }
And then create your controller like this:
# app/controllers/custom_sessions_controller.rb
class CustomSessionsController < Devise::SessionsController
## for rails 5+, use before_action, after_action
before_filter :before_login, :only => :create
after_filter :after_login, :only => :create
def before_login
end
def after_login
end
end
I found that using the Devise Warden hook cleanly allowed after login event trapping by looking for the ":set_user" :event.
In user.rb:
class User < ApplicationRecord
Warden::Manager.after_set_user do |user, auth, opts|
if (opts[:scope] == :user && opts[:event] == :set_user)
# < Do your after login work here >
end
end
end
I think this is an duplicate question. Yes you can execute code after every successful log in. you could write the code in your ApplicationController. Also have a look at http://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in. Also, check out How to redirect to a specific page on successful sign up using rails devise gem? for some ideas.
You can do something like:
def after_sign_in_path_for(resource_or_scope)
Your Code Here
end
Reference Can I execute custom actions after successful sign in with Devise?
You could also inherit from devise session's class and use after_filter for logins.
UPDATED 2022
Warden now has built-in callbacks for executing your own code on after_authentication:
Warden::Manager.after_authentication do |user, _auth, _opts|
TelegramService.send("#{account.name} just logged in")
end
Source: https://github.com/wardencommunity/warden/wiki/Callbacks#after_authentication

Making changes to the devise user controller in rails?

I have started using devise for my rails app, however i need to make some changes to the controller logic that devise has, my problem is that i assign users roles, and i want to put in params[:user][:role_ids] ||= [] in the update action so if all the roles are unchecked then it actually works.
whats the best way to do this?
class UsersController < Devise::SessionsController
def create
super
end
def update
#edit here
end
end
and make sure you update your routes.rb file:
devise_for :users, :controllers => { :sessions => 'users/sessions' }

Resources