Devise close registration but seed database with admin account - ruby-on-rails

I'm looking to completely close off my registration system (temporarily) and only have 1 admin account that can be either raked into the database or seeded.
Is this possible with Devise at all? Or will a closed off registration also close off the seed/rake task with my admin user in it?
I currently have a user model with the typical devise setup, with an admin column that is a boolean - I'm currently setting that column in development by going into rails console and manually changing it.
Any help would be brilliant!
Thanks

There is a detailed step by step in the devise wiki; but basically you can either skip generating the registrations routes:
devise_for :users, :skip => :registrations
Which would make it a single user system by making it impossible to register.
This requires the first user to be created with either a seed file or through the console.
Or you could create your own controller to handle registrations which cuts off after the first user:
devise_for :users, :controllers => {:registrations => "registrations"}
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
if User.any?
redirect_to root_path, alert: 'Only one user allowed!' and return
end
super
end
end
Unless your seed / rake task is doing something really strange like automating a web browser then this will have no effect on your seed / rake task since they usually involve directly manipulating the DB through models and do not go though controllers at all:
# Example of seeding an admin user:
admin = User.create_with(surename: 'Doe', forename: 'John').find_or_create_by(email: 'admin#example.com')
admin.add_role(:admin)

You should be able to remove the devise routes for registration and still seed in the user. That user would then be able to login/logout, as long as you still have the devise routes for sessions.

Related

Rails 5 Devise multi-user landing pages / custom profiles

I'm not sure if I'm searching for the answer using the wrong terms, but I can't find a good solution to what I'm trying to do, it can't be that unique of a scenario, but I'm a bit of a noob so I apologize if I missed something somewhere.
Rails 5 project using Devise to handle 3 users for a 2-sided marketplace (very close to taskrabbit, ect) : admin, clients, and hosts. Clients build requests, hosts bid on the requests.
When a client logs in I'd like to redirect them to a landing page that has all their current/past requests (and as a consequence the bids, etc). The same for hosts with their bids.
When an admin logs in I want to build an admin panel that lets the admin view all users/hosts.
I'm utterly confused as to how to organize the controllers/views so that clients/hosts can have their own landing page without messing up the index view for when admins log in and would (I think?) use the same clients/index view to get a list of all the users.
Any help would be greatly appreciated. Thanks!
You could redirect from within the Index controller if the logged-in user is an admin, somewhat like:
if current_user.admin?
redirect_to :admin_view
end
If the three user roles mentioned have totally different properties and meta-data, then create three different devise models and different "home-page" actions for each one of them. Redirect to their respective homepage by overriding the after_sign_in_path_for devise action. As an example, you may create a new folder named "admins" in the controllers folder and create a new file called "registrations_controller.rb"
class Admins::RegistrationsController < Devise::RegistrationsController
protected
def after_sign_in_path_for(resource)
custom_home_page_path
end
end
Repeat the above step for Clients and Hosts as well.
Update 'devise_for' lines in "routes.rb" as follows:
devise_for :admins, controllers: { registrations: 'admins/registrations'}
devise_for :clients, controllers: { registrations: 'clients/registrations'}
devise_for :hosts, controllers: { registrations: 'hosts/registrations'}
However, if you have one universal devise model (say User) and under that you have a column specifying the role, then perform the changes as given below.
In controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
protected
def after_sign_in_path_for(resource)
if current_user.admin?
admin_home_page_path
elsif current_user.client?
client_home_page_path
else
hosts_home_page_path
end
end
end
and in routes.rb
devise_for :users, controllers: { registrations: 'admins/registrations'}

Devise and a separate users table

I'm working on a rails 3.2 app that authenticates using devise.
For a goal that is not related to the application (mostly statistics) I need to create a separate users table (let's call it alt_users) that only holds some fields of the users table (name, email, and some other fields) but no password digests and other sensitive infos. Also this records don't have to be modified if a user modifies his account or deletes it.
My idea is that when a user signs up, before devise makes his job some selected fields are inserted in the alt_users table.
What is the correct way to override devise behavior in order to make this happen?
What you can do is to override Devise's RegistrationsController in the following way:
In your routes.rb:
devise_for :users, :controllers => {:registrations => "registrations"}
Then create the file app/controllers/registrations_controller.rb :
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def create
# add your data to alt_users here
super
end
end
On a side note, if you can avoid overriding Devise's controller it would be best.
Try to think of other options like a before_create callback on the User model.

Devise: user has to login again each time he closes the browser

I'm using Devise and Omniauth for user authentication.
I want the users to stay signed in for 2 weeks after the authentication. However, whenever the user closes the browser window and reopen it, he gets the login screen again.
What is the correct configuration for the user to stay connected even after the browser was closed and re-opened?
Check out this page on Devise's wiki:
https://github.com/plataformatec/devise/wiki/Omniauthable,-sign-out-action-and-rememberable
Basically, Devise does not call rememberable by default when using omniauth. If you wish to do so, simple call remember_me(#user) on your omniauth callback and Devise will do the hardwork for you. It will also use all the configuration options set in your devise initializer.
You have to extend the devise SessionsController to add cookies on log in and log out, so the controller will look like this one:
class SessionsController < Devise::SessionsController
# POST /resource/sign_in
def create
cookies[:sign_in] = "Sign in info you want to store"
# add this for expiration { :expires => 2.weeks.from_now }
super
end
# GET /resource/sign_out
def destroy
cookies[:sign_out] = "Sign out info you want to store"
super
end
end
Then you would have to add the following to your routes.rb:
devise_for :users, :controllers => { :sessions => "sessions" }
You may also set the cookie expiration time for 2 weeks.

Devise/Rails - How to allow only admin to create account for others?

I am using devise as my authentication solution and now i am thinking about authorization. In my project I (the admin) is the only person authorized to create account for others.
I wonder if there is a way to do it without to much hack. In fact, Devise doesn't allow user to access to the signup page if he is already logged in.
Thanks for your advice on it!
Setting :skip => :registrations also kills the ability for a user to edit their user info. If that's not what you are after you can instead create a (minimal) custom registrations controller and only remove the new_user_registration_path while preserving the edit_user_registration_path.
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def new
# If you're not using CanCan, raise some other exception, or redirect as you please
raise CanCan::AccessDenied
end
end
# routes.rb
devise_for :users, :controllers => { :registrations => "registrations" }
Once you do this you also need to move the directory views/devise/registrations to just views/registrations.
You can try the rails_admin gem in conjunction with Devise to handle any admin-specific tasks. You'll need to add more code to set it up, but at least you avoid hacking around the solution in terms of changing your interactions with Devise.
It actually looks like in the later versions of Devise you can just remove the "registerable" declaration from your model and it will take care of this for you.

How to debug devise/warden?

I am trying to setup devise in my rails app. It was working nicely, but now I am not able to login as any of my users I get 'Invalid email or password.' I would like to get more insight why its not authenticating.
Is there any devise configuration settings that shed some more light? i.e. what is the query being used to find the user, et c ...
Thanks!
Normally Devise not provide an accurate logging system, maybe overriding the default controller you can catch what is going wrong. Try something like this:
# app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController
def new
super # or perform some custom task
end
end
Remember then to configure the routes too.
# app/config/routes.rb
devise_for :users, :controllers => {:sessions => "sessions"}
For more details about the default Devise sessions controller take a look at this:
https://github.com/plataformatec/devise/blob/master/app/controllers/devise/sessions_controller.rb
OR
You can login with ssh to your remote server, run rails console and do manually some checks (check that users exist, try a login via console,...), alternatively you can create a rake task with some testing and run remotely.

Resources