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
#...

