How to create the first (Admin) user (CanCan and Devise)? - ruby-on-rails-3

I made authentication in my Rails 3 app fallowed by Tony's tutorial
I don't want public registrations on my app, just to create new users with Admin account, but I can't create Admin account manually, because in table Users there is encrypted password and salt that must to be generated, and I don't know how :|

You can do it from the rails console. From the command line goto the directory of your rails application and type rails console. Then enter the following code to create a user:
user=User.create!(:email=>'test#test.com',:username=>'test',:password=>'password')
This will create a user object (assuming your devise resource is called User). Now you can use the user object that you just created to set admin privileges.

I am current something like this (your details may be different) in my seeds.rb file to create my admin user for Devise.
User.new({ :email => 'admin#example.com', :password => 'password', :password_confirmation => 'password'}).save
You can execute it using rake db:seed in the terminal window.

In addition, if you are using confirmable and want to skip the requirement for a confirmation email when creating new accounts you can do something like this:
newuser = User.new({ :email => 'admin#example.com',
:password => 'password',
:password_confirmation => 'password'})
newuser.skip_confirmation!
newuser.save
This is useful if the accounts you are creating are for trusted users or if you are creating test accounts.

Related

Skip email confirmation when creating a new user using Devise

I have a user registration page and will send the information to couple of admin users that one new user registered in the site.
Now, I created the seed data with list of users (200+). So, It'll send the 200+ email to the respective admin users. Hence, I want to stop send the mail confirmation to admin users when creating new user.
For Devise, add user.skip_confirmation! before saving.
user = User.new(
:email => 'person#example.com',
:password => 'password1',
:password_confirmation => 'password1'
)
user.skip_confirmation!
user.save!
Cite: https://github.com/plataformatec/devise/pull/2296
Another option is to do something like
user = User.new.tap do |u|
u.email = 'email#server.com'
u.password = 'hackme!'
u.password_confirmation = 'hackme!'
u.skip_confirmation!
u.save!
end
In that way, you instantiate the object, skip the confirmation and save it in one step and return it to the user variable.
It's just another way to do the same in one step.

Login to other user's account with Devise+Active Admin+Switch User

I'm trying to implement switch_user gem in my existing rails 3.0.9 application.
There are two models on my application, they are
User - for my customer accounts and it has_one Account
AdminUser - This was created by ActiveAdmin
I have already enabled devise authentication for Users and ActiveAdmin also working pretty much well with AdminUser. Now from my Active Admin interface I'd like to select the Accounts and login to those account just like the account owner does. Switch user is working fine but the problem is anyone can simply login to the user accounts now if they know the urls.
http://localhost:3000/switch_user?scope_identifier=user_1
All I need is allow only an AdminUser (i.e if there is an ActiveAdmin session) to access the User's accounts.
This is how my /config/initializers/switch_user.rb looks like
SwitchUser.setup do |config|
config.controller_guard = lambda { |current_user, request| current_admin_user.nil?}
config.redirect_path = lambda { |request, params| "/dashboard" }
end
But I get this error
NameError in SwitchUserController#set_current_user
undefined local variable or method `current_admin_user' for main:Object
Is there anyway I can access the active admin session?
Code for /config/initializers/active_admin.rb
ActiveAdmin.setup do |config|
config.site_title = "MyAppName"
config.authentication_method = :authenticate_admin_user!
config.current_user_method = :current_admin_user
end
btw in my application controller I haven't created any methods for authenticate_admin_user , current_admin_user active admin works fine without them.
You need modify local config/initializers/switch_user.rb:
config.controller_guard = lambda { |current_user, request, original_user, controller|
controller.admin_user_signed_in?
}
Original lambda has 2 arguments.
Just append more (up to 4) and use it.
Don't forget restart rails server :)
OK I think I found a solution to secure the switch_user. All I did is moving the routes inside the admin_users scope
ActiveAdmin.routes(self)
devise_for :admin_users, ActiveAdmin::Devise.config do
match '/admin/switch_user', :controller => 'switch_user', :action => 'set_current_user'
end

Create New User with info from another Model - Rails 3.0

I am using Rails 3 and Devise for user authentication. I created a separate scaffold, request_new_user, and I want to have a link on the index page for all of the people who requested an account to go to the new_user_path, with their information sent as well to populate the fields. How would I set the params so I can set the values within the user controller? Or is there a better way to do this? I mainly just want to pass the new user's name and email.
You can generate devise views in your project by: rails generate devise:views .
Send your params in GET request: /signup?email=...&name=...
In registration view you can apply your params, something like:
<%= f.input :email, :value => params[:email] %>
Hope it helps.

CanCan and Devise, restricting login based on Role

I've just finished setting up Devise on a single application, using a single User model with two scopes, so I can have an /admin/login as well as a regular /users/login path. This works pretty well, my config/routes.rb file looks like this:
devise_for :users,
:path_names => { :sign_in => 'login', :sign_out => 'logout' }
devise_for :admins,
:class_name => 'User',
:skip => [:passwords, :registrations, :confirmations, :sessions],
:controllers => { :sessions => 'admin/sessions' } do
get 'admin/login' => 'admin/sessions#new', :as => :new_admin_session
post 'admin/login' => 'admin/sessions#create', :as => :admin_session
delete 'admin/logout' => 'admin/sessions#destroy', :as => :destroy_admin_session
end
This works pretty fine and dandy, I can log in to each side of the application without affecting the other. That is, the session names are separate and logging into one does not log you into the other.
Now, I've set up CanCan with my Roles model, and an Ability model, and have these defined in my database and working.
Question is, I want to be able to fill out the form on admin/login, and receive an error message because my Role doesn't allow me to log into that area. How can I accomplish this?
I am a bit confused by your question. If you are filling out the form on admin/login, then presumably you have not logged in yet?
If that's the case, then there is no current_user or current_admin and therefore nothing is passed to CanCan yet.
I have a similar set-up in my app and maintain different accounts on each side of the app. My user account is different than my admin account. If I forget and try to login to the admin side using my regular user account, I simply receive an unknown user/password error from Devise.

Rails: Integration test data

I'm new to Rails testing and I'm confuse with the nature of rails integration test data:
test "should register new user and login" do
..
# create user
post users_path, :user => {:username => "newuser", :email => "newuser#gmail.com",
:password => "secret",
:password_confirmation => "secret"}
assert assigns(:user).valid?
..
end
test "another should register new user and login" do
..
# create user
post users_path, :user => {:username => "newuser", :email => "newuser#gmail.com",
:password => "secret",
:password_confirmation => "secret"}
assert assigns(:user).valid?
..
end
In the User model i have a validation to ensure that :username and :email are unique. But how come the test was able to post both data with no complain/error/invalid? Any help is appreciated, I thought there's a single DB only for the test and the test data should've clashed. Thanks.
Good question. Before the test framework (Test::Unit) runs each test it resets the database to its original state. So before each test you are guaranteed that the DB only has the fixture data and nothing else.
This is helpful. You don't want the data from one test still to be there when you start the next test. If it were, the DB state would be inconsistent if you did something like run a test by itself (instead of the whole suite) or run tests in a different order.
The solution: you can write a test that specifically verifies that the :username and :email are unique. Before I give an example, I should mention that it looks like you wrote a functional test for this validation. This is tempting because you're verifying the behavior the user will see, but the place to test validation is in the unit tests because validation rules in Rails get pushed down to the models. (To keep validation DRY. You don't have to duplicate your validation rules across a bunch of controllers)
So here's one way you could write the unit test:
test "should validate unique email" do
attributes = { :username => "newuser", :email => "newuser#gmail.com", :password => "secret", :password_confirmation => "secret" }
# create user
user1 = User.create(attributes)
assert_nil user1.errors.on(:username)
assert_nil user1.errors.on(:email)
# create another user with the same name and email
user2 = User.create(attributes)
assert_not_nil user2.errors.on(:username)
assert_not_nil user2.errors.on(:email)
end
For a good article about this, see John Nunemaker's blog post from two years ago. Ignore the accidental HTML tags in his code samples. Nunemaker is an awesome Rails blogger.
There are some alternate testing libraries like Shoulda that have built-in functions to validate that your model validates uniqueness. But since you're new to Rails I'd recommend sticking with the default test framework for now. (In fact the folks at 37Signals who invented Rails still use the default too, so that says a lot for it. I also prefer to stick with the default.)
By the way, you can format code in a StackOverflow question by indenting it with four spaces.