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'}
Related
I am using Devise in my Rails 5 project and I would like to temporarily disable new user registrations. I know I can remove the view's link, or edit the routes file to accomplish this, but that requires a change to code with a new deployment. I would like to add an option in my administrative console to disable the ability for new users to register for a period of time.
I have this functionality enabled, but it's a hacky work around. When I disable the ability for people to register, all I am currently doing is hiding the 'new user registration' link in the devise view. Anyone who knows the default paths can work around this.
How can I change this functionality at runtime?
Follow This Link for overriding the Registration Controllers for Devise.
Basically you need to override Devise default Registeration controller and put up a before filter for new & create action which checks if admin allows to create new users if not then redirect to root_path or whatever path you want.
Alter the devise_for line in config/routes.rb to override the registration controller:
devise_for :users, controllers: { registrations: "registrations"}
app/controllers/registrations_controller.rb:
class RegistrationsController < Devise::RegistrationsController
before_action :check_new_registration_allowed?, only: [:new, :create]
protected
def check_new_registration_allowed?
redirect_to root_path unless ##allow_new_registration
end
end
Please be noted that I used ##allow_new_registration global variable to check if new registration is allowed. You can turn this on/off after admin action. Alternatively it would be good if you store these information in DB and query it.
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.
I am building a mobile version of our website and I would need to create a different views for sign up/in for mobile users. These two actions should be in a different controller.
My problem is that I don't know how to prepare instances for sign up/in for Devise in a different controller(s)...
How to make that?
Thanks
You mean you want to implement sign up/in in your own controller?
If so, you can modify routes.rb first
devise_for :users, :controllers => { :sessions => "controllername" }
And modify the controllername_controller.rb
class ControllernameController < Devise::SessionsController
def create
# your implementation
end
def destroy
# your implementation
end
end
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.
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.