Restful Authentication with rails 2

January 19th, 2008 | Ekerete

I recently had to build an authentication system into a project and seeing as the restful authentication plugin was getting such buzz, I decided to try it out.

The problem was, most of the information I found on the internet was dated and I had to make a couple of changes to get it to work on Rails 2.0. This site and this forum post were really helpful. This post documents the steps I took (or rather, the steps I’ll take next time I use it) to get the plugin working. It assumes you already have a rails application running and want to add authentication to it.

  • Install the plug-in
    Open up a console window and navigate to the root of your application.
    Use script/plugin to install the plugin.

    ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/restful_authentication/
  • Run the generator
    The generator sets up your controllers, model, views and observer as well as modify the routes.rb file (sets up session and users as resources). The session controller is used for signing in and out of the system while the user controller takes care of the rest.

    If you do not need a user activation system built into the system, type the line below:

    ruby script/generate authenticated user sessions

    If you need a user account activation system, use the line below. The rest of this post will assume the system includes user activation (the system is a lot simpler without user activation enabled).

    ruby script/generate authenticated user sessions --include-activation
  • Run the migration
    The system also generated a migration file. Run the migration with:

    rake db:migrate
  • Modify the routes file
    Open up config/routes.rb and add to the named route section:

    map.activate '/activate/:activation_code', :controller => 'users', :action => 'activate'

    While the routes file is still open, add more named routes (giving the user actions nice, friendly urls)

    map.signup '/signup', :controller => 'users', :action => 'new'
    map.login '/login', :controller => 'sessions', :action => 'new'
    map.logout '/logout', :controller => 'sessions', :action => 'destroy'
  • Add an observer (required for user activation emails)
    Add an observer to config/enviroment.rb (within the Rails::Initializer.run block) :

    config.active_record.observers = :user_observer

    At this point, the basic system should be working. Start up your development server and go to http://localhost:3000/signup. You should see the sign up form.
    Also try http://localhost:3000/login to confirm it’s fine.

  • Set up ActionMailer (required for user activation emails)
    The rails config/environment.rb file includes a Rails::Initializer.run block and prior to Rails 2, configuration code went in there.
    With Rails 2, there’s now a directory (config/initializers) where seperate, discreet bits of configuration are placed in files of their own.
    These are automatically loaded after plugins are loaded when Rails starts up.

    Create a new file called mail.rb in the config/initializers directory (you can actually call the file anything you like). SMTP setting will go into this file.
    Rails 2 also changed the variable for ActionMailer settings from server_settings to smtp_settings
    Place the following into the mail.rb file:

    ActionMailer::Base.delivery_method = :smtp
    ActionMailer::Base.smtp_settings = {
        :address => "mail.example-domain.com",
        :port => 25,
        :domain => "www.example-domain.com",
        :authentication => :login,
        :user_name => "user@example-domain.com",
        :password => "secret"
    }

    :address and :port - Determines the address and port of the SMTP server you’ll be using. These default to localhost and 25 , respectively.
    :domain - The domain the mailer should use when identifying itself to the server (usually the top-level domain name of the machine sending the email).
    :authentication - One of :plain, :login or :cram_md5. Should be omitted if the server does not require authentication. Also omit :username and :password options if you omit this parameter.
    :username and :password - Mail account login credentials. Required if :authentication is set.

  • Modify the activation email parameters
    Open the production and development configuration files, config/environments/production.rb and config/environments/development.rb respectively.

    In the development config file:

    SITE_URL = "localhost:3000"

    and in the production:

    SITE_URL = "example-domain.com"

    You need to restart the server for these settings to take effect.Open app/models/user_mailer.rb. Change:

    @body[:url]  = "http://YOURSITE/activate/#{user.activation_code}"

    to:

    @body[:url]  = "http://#{SITE_URL}/activate/#{user.activation_code}"

    Change:

    @body[:url]  = "http://YOURSITE/"

    to:

    @body[:url]  = "http://#{SITE_URL}/"

    Change the setup_email block settings (ADMINEMAIL and YOURSITE) to your desired settings.

    Open the email template files (app/views/user_mailer/activation.html.erb and app/views/user_mailer/signup_notification.html.erb) and modify as desired.

    And that’s it. The system should now be working.

    Note: You need to include flash[:notice] and flash[:error] in your templates or layout to view the status messages e.g. just before the <%= yield %> line in app/views/application.html.erb, type:

    <p style="color: green"><%= flash[:notice] %></p>
    <p style="color: #990000"><%= flash[:alert] %></p>

Springloops - stressless subversion

December 31st, 2007 | Ekerete

We’ve been using Springloops for a couple of months now and all I can say is ‘Wow!’.

Springloops claims to be “a unique source code management tool focused on web development teams. It allows you to code in parallel and share your code safely concentrated on results, not on lost changes or overwritten files”. It delivers. Working from home was never this slick and it removed the need to set up our own version control server.

Springloops is a hosted service and the amount of storage space and number of projects you get depends on what plan you sign up to. There is even a free account giving you up to 10Mb of storage and 3 projects. However, I think the sweet spot is the ‘ Garden’ plan. With this plan (and all higher plans) you get the automatic deploy option and we use this to deploy any code we commit to our staging server via FTP.

The interface is well laid out with the dashboard showing recent account activity and links to your projects. You can also set up users and restrict their access to specific projects.

This service has become integral to our workflow and I can’t recommend it enough.

Update: Since we signed up for Springloops we’ve seen a couple of other hosted version control systems. Beanstalk and Versionshelf look promising.

Giving up on mongrel_cluster on windows

December 30th, 2007 | Ekerete

That’s it! I’ve given up trying to deploy a Rails app with capistrano from windows. Just spent two days trying to set this up (even tried cygwin) with no luck.

The solution? VirtualBox. I have just gone from installing Ubuntu server in a virtual machine to deploying the application in thirty minutes. It’s a bit long-winded commiting to subversion from windows and changing to the virtual machine to use capistrano but it works so I’m happy.

Why am I still working in windows? I ask myself that all the time but I’ve got so much stuff installed and set up on my laptop the thought of changing is depressing. Also use Visual Studio Express once in a while and that only works on windows.

Two thumbs up for VirtualBox.

Update: Finally got Capistrano to work on windows. About time!

Expected identifier, string or … - say what?

October 4th, 2007 | Ekerete

While working on a recent project with the excellent Prototype and Scriptaculous javascript libraries, I came across a frustrating error in IE7 (and I’m sure IE6 although I didn’t test it). The page worked beautifully in firefox but came up with “Expected identifier, string or number” on IE.

Normal debugging procedures (firebug, web developer toolbar) failed to show where my error was. To its credit, the Microsoft script debugger actually showed me the function with the error but at that time I didn’t see it as an error. After a couple of hours of hair-pulling and googling, I came across this post.

Apparently, a comma in my function was the culprit. My problem code was:

function xajax_getOptions(badgeId) {	
    new Ajax.Request($F(absolute-url) + /ajax/options,
    {
	method:post,
 	parameters: {catid: badgeId},
	onSuccess: function(transport){
 		var response = transport.responseText;
		$(badgecell).innerHTML = response;
 		getBadgeImage();
    	},
	//onFailure: function(){ alert(”an error occurred”); }
   });
}

Notice that I commented out the onFailure parameter without taking out the comma at the end. Firefox ignored that, IE choked.

A big thank you to Khlo for showing the way.