Pt-I-2
Alkasai says:
Here is how i did it. This is the OLD code in application_controller.rb:
def authorize
unless User.find_by_id(session[:user_id])
session[:original_uri] = request.request_uri
#flash[:notice] = "You're loged in as #{params[:name]}"
redirect_to :controller => 'admin' , :action => 'login'
end
end
And this is the NEW code in application_controller.rb:
def authorize
if User.count == 0
if request.path_parameters[:controller] == 'users' and request.path_parameters[:action] == 'create'
#do nothing. let the users controoler verify that everything is correct
elsif !(request.path_parameters[:controller] == 'users' and request.path_parameters[:action] == 'new')
flash[:notice] = "Please create Admin User"
redirect_to :controller => 'users' , :action => 'new'
end
elsif !User.find_by_id(session[:user_id])
session[:original_uri] = request.request_uri
redirect_to :controller => 'admin' , :action => 'login'
end
end
This should redirect all the pages to ’/users/new’ (except the ’/store’ of cause), when there are no users in DB. However, only page that is not redirected for some reason is ’/admin/login’. Anybody knows why?
unknown
This is a quick and dirty solution, just creates a user with the given credentials when no user exists in the database. In login_controller.rb:
def login
session[:user_id] = nil
if request.post?
if User.count.zero?
user = User.create(:name => params[:name],
:password => params[:password],
:password_confirmation => params[:password])
else
user = User.authenticate(params[:name], params[:password])
end
if user
session[:user_id] = user.id
uri = session[:original_uri]
session[:original_uri] = nil
redirect_to(uri || { :action => "index" })
else
flash[:notice] = "Invalid user/password combination"
end
end
end
Cosmin Lehene:
This will pass over authorize method like a valid login as long as no users are created in the database and will flash a warning notice permanently. After the first user is created it will ask for credentials.
In application.rb change the authorize method:
def authorize
unless User.find_by_id(session[:user_id]) or User.count == 0
session[:original_uri] = request.request_uri
flash[:notice] = "Please login"
redirect_to(:controller => "login", :action => "login")
end
if User.count == 0
flash[:notice] = "Please create the first user account"
end
end
end
Of course, in order to get the required behavior, you have to modify the login action in login_controller.rb also:
def login
session[:user_id] = nil
if User.count == 0
redirect_to(:action => "add_user")
elsif
[...]
k9d says:
I followed Cosmin’s example except I wanted the user to be redirect to the page where they can create the first user account. To achieve this I modified def authorize in application.rb to look more like this
#...
if User.count == 0
flash[:notice] = "Please create the first user account"
redirect_to(:controller => "login", :action => "add_user")
end
#...
All is well except the before_filter in login_controller.rb doesn’t allow the un-authorized user to see add_user. Is there a way to work around this problem?
Also, a handy mysql command if you need to manually clear out the last user, to Delete a row(s) from a table>
DELETE from [table name] where [field name] = 'whatever';
Matt says:
To allow an unauthorised user to get to the add_user page, check the path_parameters of the request:
def authorize
unless User.find_by_id(session[:user_id]) or User.count == 0
session[:original_uri] = request.request_uri
flash[:notice] = "Please log in."
redirect_to(:controller=>"login", :action=>"login")
end
if User.count == 0
if request.path_parameters[:action]=="add_user" and request.path_parameters[:controller]=="login"
#As we are already on our way to the add_user action, do nothing here.
else
flash[:notice] = "Please create an account."
redirect_to(:controller=>"login", :action=>"add_user")
end
end
end
jwat says:
Matt’s code worked for me. However, as good programming practice, it makes more sense to write the logic for zero user counts as so:
def authorize
unless User.find_by_id(session[:user_id]) or User.count == 0
session[:original_uri] = request.request_uri
flash[:notice] = "Please log in."
redirect_to(:controller=>"login", :action=>"login")
end
if (User.count == 0 and request.path_parameters['action'] != "add_user")
flash[:notice] = "Please create an account."
redirect_to(:controller=>"login", :action=>"add_user")
end
end
I suppose you can check for the controller params as well, but I didn’t bother.
h3. Dimitris says: All you need to do is go to application.rb and change the check in the authorize method to:
unless User.find_by_id(session[:user_id]) || User.count == 0
In this way, authorization is bypassed if there are no users in the DB. As soon as you create a user, you’re asked to login and everything works as before.
h3. Valerie says:
Nice solution, Dimitris! I also added a flash notice, as Cosmin mentioned.
def authorize
flash[:notice] = "Please create an admin user" if User.count == 0
unless User.find_by_id(session[:user_id]) || User.count == 0
session[:original_uri] = request.request_uri
flash[:notice] = "Please log in"
redirect_to :controller => 'admin', :action => 'login'
end
end
Grazybom
Here is my simple solution: admin_controller.rb
def login
if request.post?
user = User.authenticate(params[:name], params[:password])
if user
session[:user_id] = user.id
uri = session[:original_uri]
session[:original_uri] = nil
redirect_to(uri || { :action => "index" })
elsif User.count.zero?
flash[:notice] = "Create your first administrator account. Please, logout after you have created your new account and login with your new credentials."
redirect_to(:controller => "users", :action => "new")
else
flash.now[:notice] = "Invalid user/password combination"
end
end
end
and application.rb
def authorize
unless User.find_by_id(session[:user_id]) or User.count.zero?
session[:original_uri] = request.request_uri
flash[:notice] = "Please log in"
redirect_to :controller => 'admin', :action => 'login'
end
end
Even though, each action is available via get request untill the first account is created.
m1kee
I didn’t like how Grazybom’s solution allowed full access to the entire site as long as there wasn’t any user account created.
Here’s my solution:
app/controllers/application.rb
def authorize
unless User.find_by_id(session[:user_id]) || User.count.zero?
session[:original_uri] = request.request_uri
flash[:notice] = "Please log in"
redirect_to(:controller => 'admin', :action => 'login')
end
if (User.count.zero?)
if !(request.path_parameters[:controller] == 'users' and request.path_parameters[:action] == 'new')
if !(request.path_parameters[:controller] == 'users' and request.path_parameters[:action] == 'create')
redirect_to(:controller => 'admin', :action => 'login')
end
end
end
end
#...
app/controllers/admin_controller.rb
class AdminController < ApplicationController
def login
if User.count.zero?
redirect_to(:controller => 'users', :action => 'new')
end
#...
As an addition, to ensure user account creation:
app/controllers/store_controller.rb
class StoreController < ApplicationController
before_filter :find_cart, :except => :empty_cart
def index
if (User.count.zero?)
redirect_to(:controller => 'admin', :action => 'login')
end
#...
AndriySand
Hi! I resolved this problem this way. Now I work with Rails 1.8.02 First I commented the method after_destroy in order be able to delete last user.
# def after_destroy
# if User.count.zero?
# raise "Can't delete last user"
# end
# end
Then I wrote ‘except ‘ in ‘login_ controller’ this way in order be able to add user to non-administrator person only once.
before_filter :authorize,:except => if User.count == 0
:add_user
else
:login
end
After I added couple strings of code in ‘authorize’ method in application.rb and this method looks like this
private
def authorize
if User.count == 0
flash[:notice] = "Please create first admin"
redirect_to(:controller => "login", :action => "add_user")
else
unless User.find_by_id(session[:user_id])
flash[:notice] = "Please log in"
redirect_to(:controller => "login", :action => "login")
end
end
end
end
Good luck to every one!
Pablo says
I’ve solved this problem in very few lines
class ApplicationController < ActionController::Base
layout "store"
before_filter :create_first_admin
before_filter :authorize, :except => :login
...
protected
def create_first_admin
flash[:notice] = %q{There are currently no users in the database.
Please create one administrator user} if User.count == 0
ignore1 = (controller_name+action_name != "usersnew")
ignore2 = !request.post? || controller_name != "users"
if User.count == 0 && ignore1 && ignore2
session[:user_id] = nil;
redirect_to :controller => :users, :action => :new
end
end
...
end
Only problem is, I didn’t know how to use the :except option in before_filter so that I can also say that the users controller must be ignored and hence I did it on my own in the function (this is the only part I don’t really like).
I decided that not even the store should be available when there are any user in the database. What is the point of browsing products, adding stuff in the cart, check it out when there is no one that will take your order?
illbzo1 says
Reading through a few of the methods shown above, here’s what I came up with.
First, I add a skip_before_filter method to :users_controller. We don’t want to be redirected while accessing the :new method, or while using it to :create a user.
skip_before_filter :authorize, :only => [:new, :create]
Next we update application_controller. Using an unless/or combination, we can check for either a logged in user, or an absence of users, then apply methods depending on that result.
def authorize
unless User.find_by_id(session[:user_id]) or User.count.zero?
redirect_to login_url, :notice => "Please log in"
end
if User.count.zero?
redirect_to new_user_path, :notice => "Please create a user"
end
end
end
MarkB says
I solved this similarly to illbzo1 above. I added
skip_before_filter :authorize, :only => [:new, :create]
to the top of users_controller.rb so that I didn’t get a redirect loop and added the below code to the respond_to block of the create method after the save of the record which checks if there is now only one user in the database and if so, sets the session id to to be that user ID so that the authorize filter will allow the redirect.
if User.count == 1
session[:user_id] = User.find_by_name(@user.name).id
end
I then altered the authorize method in application_controller.rb as below to check for an empty User table and redirect if there is.
def authorize
if User.count.zero?
redirect_to new_user_path, notice: "Please create the first user account"
else
unless User.find_by_id(session[:user_id])
redirect_to login_url, notice: "Please log in"
end
end
end
John Lane says
I did this by just creating a user if none exists. The user is created with whatever is entered in the login box:
class SessionsController < ApplicationController
skip_before_filter :authorize
def new
end
def create
if User.count == 0
user = User.new(name: params[:name],
password_digest: BCrypt::Password.create(params[:password]))
user.save
else
user = User.find_by_name(params[:name])
end
if user and user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to admin_url
else
redirect_to login_url, alert: "Invalid user/password combination"
end
end
def destroy
session[:user_id] = nil
redirect_to store_url, notice: "Logged out"
end
end
Pierre says
If no admin is in the database a login of anybody will redirect to users/new to create a new user. After the user is created the login page is displayed to login with the new user just created.
In the session controller I have added rows marked with #*
def create
if User.count.zero? #*
redirect_to new_user_path #*
else #*
user = User.find_by_name(params[:name])
# ...
end #*
end
In the application_controller.rb I have added rows marked with #*
def authorize
return if User.count.zero? #*
# ...
end

