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
Related
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
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.
Many people say that you just have to add the :username attribute in the user model if you want to create a :username attribute:
user.rb:
attr_accessible :email, :password, :password_confirmation, :remember_me, :username
I'm not sure if something like :username is already assigned in the database (just like you install Devise.)
If not, how can I add it to the database and what other things would I have to do? (Sorry, I'm a Rails beginner.)
Yes, at least for Devise 2.0 you need username in your database if you want to save it.
Create a migration - this will add a script to create the username field to your user table. Run the following from your terminal.
$ rails generate migration add_username_to_user username:string
run the migration (again from terminal)
$ rake db:migrate
After that your user table will have a username field added to it.
Then you'll need to edit the Devise views so users can register with a username. For that take a look at "Configure Views" section on the github Devise page
But basically, run the following to create the devise views (by default they're stored in the devise engine so you don't see them on disk)
$ rails generate devise:views
Then go in and edit the appropriate view file. For registration it's
app/views/devise/registrations/new.html.erb
You'll also want to show the username on their "edit" page. That's under
app/views/devise/registrations/edit.html.erb
You'll need to add current_user.username somewhere on that "edit" view. But you'll get an error saying you can't access username so make it an accessible attribute
# User.rb - this is your user model
attr_accessible :username
You're lucky I just did this yesterday so I remember all the steps :)
No, you do not need to do that. If i remember correctly, the default username column is named 'login'. To access that under username, you can just create a virtual attribute in the User class, like :
def username
login
end
This would just return the login value as username.
You can find out more about virtual attributes here :
http://railscasts.com/episodes/16-virtual-attributes
EDIT:
Dty is right that this column is not there, so for detailed information on doing that :
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address
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.
I am developing a rails application in which I have two models User and Client.
User is backed by devise and is responsible for authentication and has_one Client which holds the client details for a given user. This relation is always present as I ensure that a Client model is created whenever I create a User.
For the administration area I am using ActiveAdmin. Now, when I try to create a User through the administration interface I use a form like this:
form do |f|
f.inputs :username, :email, :password
f.inputs :name => "Client", :for => :client do |client|
client.inputs :name, :address, ...
end
end
The problem is that either the User nor the Client are saved and the page is reloaded with validation errors. I have checked rails console and there's a WARNING: Can't mass-assign protected attributes: client_attributes message every time I try to create a User.
I have searched over this issue and found that in order to allow for mass-assignment one had to define attr_accessible for each of the fields allowed for the assignment. So, I had put this directive in Client model for each of the fields mentioned above and the message keeps appearing, preventing the models to be properly saved.
Does anyone have a clue on this?
The problem is not in your Client model, but in your User model - because this is the primary model you are trying to create. All you need to do is to add client_attributes to the list of attr_accessible attributes in your User model, just as the error message in the log files says, e.g.:
class User < ActiveRecord::Base
attr_accessible :client_attributes
end
I imagine you already have a list of accessible attributes in the User class. So just add client_attributes to the end of that list.
The changes you made to your Client model (i.e. adding a list of attributes to attr_accessible) is not needed for this to work. If you want, you can also go ahead and undo that.