Every repository with this icon (
Every repository with this icon (
User Authentication
User Authentication
The way the plugin works is simple. The first thing you do is create the models and migration:
script/generate authenticated user account
(In older versions of the plugin, you needed to create the migration separately:
script/generate authenticated_migration
This should no longer be necessary.)
This will not only create your User model, but an Account controller, some unit and functional1 tests, and some libraries in lib/. Once that’s done, you can move the include AuthenticatedSystem from app/controllers/account_controller.rb to app/controllers/application.rb. This makes all the authentication methods available to all controllers.
Requiring Authentication
To require logins for all actions, use this in your controllers:
before_filter :login_required, :except => [:login]
To require logins for specific actions, use this in your controllers:
before_filter :login_required, :only => [ :edit, :update ]
To skip this in a subclassed controller:
skip_before_filter :login_required
Here are other available methods for your views and controllers:
- logged_in? – Returns true if the user is currently logged in.
- current_user – Returns an instance of the currently logged in user.
You can override the #protect? method in your controller to only protect certain actions:
- don’t protect the login and the about method
def protect?(action)
if [‘login’, ‘about’].include?(action)
return false
else
return true
end
end
You can also override #authorized? in your controller to restrict the actions based on the user:
- only allow nonbobs
def authorized?(user)
user.login != “bob”
end
Note: there was a typo. It’s authorized? with a “d?”. The source code has a typo in the explanatory comments, too.
Question: How do you do both?
I have a controller that needs multiple levels of access control.
- Some methods should be available to all viewers (view posts, etc.)
- Some methods should only be available to viewers who have registered and are logged in (comments)
- Some methods should only be available to logged-in users with the admin flag set on their id (delete, post, etc.)
I can, of course, refactor things into separate controllers, but I’m a bit confused on what happens to MVC when the view ends up with references to things in a different controller. What I used do to is have an “admin_required?” filter (I think I hacked it into authenticated_system.rb), but I lost it with a recent update of my copy of the plugin.
Answer
I needed the same thing, and I was able to accomplish it by accessing the action_name variable in the overridden authorized? method, like this:
- protect the new and create method for only admins
def authorized?(user)
if [‘new’, ‘create’].include?(action_name)
return false unless user.is_admin?
end
return true
end
You could refactor that (untested):
def authorized?(user) user.is_admin? || ![‘new’, ‘create’].include?(action_name) endIf your lib/authenticated_system.rb implementation of authorized? does not take a parameter, you must modify the method declaration above to avoid complaints about the method requiring one parameter but zero being given:
def authorized?(user = current_user()) … endAnother Answer
You can use
def authorized? return current_user.is_admin? endso that you do not have to refactor lib/authenticated_system.rb
Another thing I found is that you may like to override access_denied method so that it returns an error mesage or HTTP Forbidden, instead of redirecting to the login page.
Tests
You need to include AuthenticatedTestHelper in test_helper.rb. The tests for actions in your controller using the :login_required filter will need to login before calling the action. One way to login is to use the fixture :users in the test class, then call login_as :quentin in either the test methods or setup method.
Tiny improvement
If the user fails to log in (say they forgot to activate the acct, or the password is bad), it would be nice to remember the login they entered. To do this, change the account_controller.rb
def login return unless request.post? @login = params[:login] #add this variable- rest of method goes here
end
then in the view login.rhtml, you can change the login field like so:
<%= text_field_tag ‘login’, @login %>





