Rails 4 : Customize Devise 3.1.0 for multiple role - ruby-on-rails

I'm having an issue using Devise. Well this is not really an issue but more a "I don't know how to do".
I'm actually using Devise 3.1.0 on my Rails 4 application. So far I only had my sign up through which users could go and register themselves into the system.
The problem is that now, I'm adding groups and roles to every user since each user gonna belong to a specific group (a company per se). So in that case, when a user first register, he register as admin and create his company. But let's say that from the inside of this application, this admin wants to create other users which all belongs to that sepcific company.
I know I could override the Devise::RegistrationController but looking at their original update method makes me feel that the code gonna be bloated if I copy their code and hack around mine in order to make it works.
My concern is especially about the strong parameters. Let me explain, actually I override the account_update_params on Devise::RegistrationsController as it :
protected
def account_update_params
params.require(:user).permit(:lastname, :firstname, :email, :current_password, :password, :password_confirmation)
end
But if I want to add account from the application as admin, I need to also allow :role which can be a security issue in the register form. What if someone try to inject something into role while register?
How to do it the best way to allow :role only inside the application but not when logout?
Thanks to everyone

Yes I too hate overwriting devise controllers. Part of the problem with devise is that it can be somewhat rigid and uncustomizable.
In your routes.rb file, create a new route.
get '/users/sign_up_as/:role' => 'devise/registrations/#new', :as => 'new_user_registration'
and then modify the devise registration view with the line
<%= f.hidden_field :role, :value => params[:role] %>
To make a link for sign up you could do
= link_to 'Sign Up', new_user_registration_path(:role => 'admin')
Also keep in mind that you are not required to use the devise registration controller for the form itself. If you run User.create, devise will still send the confirmation email, etc.

Here is how I do it
Assumptions:
1. When a user signs up, he is the admin for the new company
2. Users can be created in app by admins or some other logic that you will apply
First, create an after_create for the User model in app/models/user.rb
class User < ActiveRecord::Base
after_create :set_account_and_admin
protected
def set_account_and_admin
if self.account_id.nil?
#account = Account.create!
self.update(account_id: #account.id, admin: true)
end
end
Then override devise create in app/controllers/registrations_conroller.rb
def create
build_resource(sign_up_params)
if current_user
resource.account_id = current_user.account_id
end
#...rest of devise stuff taken from the gem
end
Now when someone goes to your sign up app and puts in user/password they will get a new account and the User model will create a new account for you and setup that new user as an admin.
If that user logs in they can create new users then devise will see that the user is logged in and assign the new users to the current users account.
Now you can add whatever logic for admin/groups and who can create new users and not have to worry about adding the logic to the form.
Another alternative to this is to make a separate action in the controller like 'inappcreate' and route to that in the user _form.

Related

Is it possible to hook up Devise Registration Controller with Administrate dashboard?

I am creating a rails employee dashboard app where I am able to view a list of employees. For this application, I am the only user that should be able to view the administrative dashboard page. I've implemented my admin functionality by using the nifty administrate gem. An example app that showcases the dashboard can be found by viewing clicking this url Administrate example. My dashboard is identical and is nothing special. However, I will run into the occasion where I need to create other users/amins (Human Resources) to log in and to be able to edit, remove employee listings.
For authentication, I am using the awesome devise gem and am successfully able to login, signup, signout, etc. Here is the catch though. I need to be able to create new users through the administrate dashboard. I have the dashboard set up to display the user fields but I am currently unable to create a user. Here is a picture of my user dashboard for reference
The problem I am facing is that when I enter a password for Encrypted password I am unable to do so because of the Password can't be blank validation.
Viewing my logs, I am able to see that when I go to devise's signup page, it goes to a Devise::RegistrationsController while creation of my User with the administrate gem goes through Admin::UsersController. Surely, someone in the community has used a combination of creating users through an admin dashboard with devise. Does anyone have any recommendations of how to customize this functionality?
This seems like a problem with strong params. You have to sanitize those parameters. Cleanest solution, at least for me, is to override the RegistrationsController like so:
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:email, :password, :password_confirmation) # list every parameter you'd like to register with
end
end
and map this controller in routes.rb like so:
devise_for :users, :controllers => { registrations: 'registrations' }
You can get inspired in this article.
Also I've noticed that you are trying to manipulate with encrypted_password field. That's not a good idea. Devise will handle that for you. You can render the input for password instead (that might as well be the issue all along).
The parameters seems to be the issue. You are trying to set protected parameters. Try sending only the following parameters.
[:name, :email, :password, :password_confirmation, :mobile ]
Make sure you have permitted above parameters in Admin::UsersController
After adding the user you have to confirm the user, if you have :confirmable in your user model. You can do so in Admin::UsersController after creation of user object.
user.confirm

Rails: One User Model but need different info on registration

I have one user model and within that model I have roles (admin and general). I am using Devise https://github.com/plataformatec/devise and CanCan https://github.com/ryanb/cancan.
An admin creates the master account during their registration and then can register other users as well as edit their accounts. This works.
Finally, I have changed it so that the users can log in using their username and not email because email is not necessary for the general user.
My current (main) registration form (used only by the admin) requires the following information: First Name; Last Name: Email; Username and Password. I know that it is necessary for me to both validate certain fields and also make it so that usernames and email are unique. Both I know how to do.
USER MODEL
validates :username, :email, :password, presence: true
DB MIGRATE
add_index :users, :email, :unique => true
My problem is that when the admin creates the other users email is not applicable and also I want to include additional fields. Because email is not necessary and because I am using a single user model, validating that field or making it unique will not work. Or I do not think it will work?
If I do not want to separate out the model is their another direction I can approach this to solve the problem. I am thinking two registration forms -- but still the issue of validation and uniqueness will be present.
Any guidance would be appreciated.
Have you considered a method in your application controller to create users like so:
def create_new_user
u = User.create(:email => "guest_#{Time.now.to_i}#{rand(99)}#example.com", :password => params([:password]), :username => params([:username]))
u.save!
end
You could create a form that admin could use to get username and any other parameters you need to this method.
Alternatively, you can generate the devise views and customize them to suit your needs.
rails generate devise:views
Then you can move :email into a hidden field (it will still be present and so pass validation) in the form and set it randomly like above. This will handle the unique issue. You can also add other attributes like you wanted.
Keep in mind though that if you want to create a Devise resource while signed in as a devise resource, you'll have to customize a few things in the registrations controller.
Devise has some good info on custom views. https://github.com/plataformatec/devise

Allow users to create other users in Devise?

Sort of a Rails beginner here.. My application uses Devise for authentication. What I need it to do is allow users, once signed in, to create other users that belong to the same organization as him.
Problem is I can't just use the default Devise new registration form since it doesn't allow me to access it when I'm signed in (I'm thinking I can override this by generating my own User controller?).
Plus, the user table has an organization_id (automatically created on signup) and I need the form to pass the current_user.organization_id for organization_id, and the default form won't let me do that.
Any suggestions?
You'll have to create a custom form that'll have all the required user fields and pass the form values to one of your controllers which will take the params something like this:
def create
User.create!({:email => params[:email], :roles => ["role/organization here"], :password => params[:password], :password_confirmation => params[:password_confirmation] })
end
In addition to this you should secure this action with one of the before_filter which will check if the user is currently logged in and able to create new users?
Hope that helps.

anonymous and registered user implementation with acts_as_commentable?

I am using acts_as_commentable and am curious if anyone has any good ideas on how to allow for anonymous and registered users to post comments? Meaning, if a registered user is authenticated, I want the comment to be marked with their name, etc. But I also want an anonymous user to be able to comment and have a name and email address recorded. I am using Devise for authentication.
I have an idea on how to make this work but it feels a little hacky to me. Wondering if anyone has any thoughts.
I don't know your plugin, but if you use this one (https://github.com/jackdempsey/acts_as_commentable), it seems very basic...
The Comment model has a relation to a user which is not mandatory.
So in your new comment form, I would just add two text_field_tags if the user is not logged (text_field_tag :first_name, text_field_tag :last_name).
And I'd just write the create action for comments like this :
def create
#comment = Comment.new(:commentable => #your_object, :user => current_user, :first_name => params[:first_name], :last_name => params[:last_name])
...
end
if the user is not logged, current_user will be nil and that won't cause any problem.
You can write an helper method to display the name for a comment depending it has a user or not like this...
# Displays the user's login if any or else the first name and last name
def displayed_name(comment)
comment.user ? comment.user.login : "#{comment.first_name} #{comment.last_name}"
end

Creating an additional related model with Devise

I've started to implement a new project using Devise, which is pretty fantastic for handling users. However, when a user signs up, they're not just creating a User model, but also need to create a related Account model that represents the company. Additional users will also belongs_to this Account model.
I can't seem to find a hook for this in Devise, though it seems like a pretty common pattern. What's the best practice for this?
I should also mention that there are a couple of fields for the Account that need to be provided on the sign_up form, so just something like this in the User model:
after_create :make_sure_account_exists
def make_sure_account_exists
if self.account.nil?
#account = self.create_account({ :company_name => '???' })
end
.. as I'm not sure how to get the company name.

Resources