Topic: RoR 2.0.2 :: Very simple authentication from scratch in 15 steps

RoR 2.0.2 :: Very simple authentication from scratch in 15 steps

1.- rails pm -d mysql [ Creating a rails project called pm ]

2.- cd pm [ Change directory to the pm directory ]

3.- Edit your config/database.yml with your db user/password [ No explanation required ]

4.- rake db:create:all
[ This will create 3 databases: pm_development,pm_test,pm_production
* Nice thing would be to see a message of the result of what is doing perhaps in future releases ]

5.- ruby script\generate scaffold project title:string description:text [ Create files & migration files for a projects table with the fields title & description - yes timestamp will be by default included ]

6.- ruby script\generate controller sessions login logout [ This controller will take care of the authentication ]

7.- lets run our migration...
rake db:migrate
c:\ruby\railapps\pm>rake db:migrate
(in c:/ruby/railapps/pm)
== 1 CreateProjects: migrating ================================================
-- create_table(:projects)
   -> 0.0940s
== 1 CreateProjects: migrated (0.0940s) =======================================


8.- Let's secure the Index Projects page for the New Project:
#app/views/projects/index.html.erb
Replace:

    <td><%= link_to 'Show', project %></td>
    <td><%= link_to 'Edit', edit_project_path(project) %></td>
    <td><%= link_to 'Destroy', project, :confirm => 'Are you sure?', :method => :delete %></td>

With:
    <td><%= link_to 'Show', project %></td>

    <% if admin? %>
    <td><%= link_to 'Edit', edit_project_path(project) %></td>
    <td><%= link_to 'Destroy', project, :confirm => 'Are you sure?', :method => :delete %></td>
    <% end %>


...

at the end of the file apply for the new project:
...

    <% if admin? %>
<%= link_to 'New project', new_project_path %>
    <% end %>

[ This will only show the Edit and Destroy links if admin? is true ]

9.- Lets declare this important admin? method in the Application Controller to make it accessible for all the models.
#app/controller/application.rb

class ApplicationController < ActionController::Base
  helper :all # include all helpers, all the time

Add the following code:
  helper_method :admin?

  protected
  def authorize
    unless admin?
      flash[:error] = "unauthorized access"
      redirect_to home_path
      false
    end
  end

  def admin?
    session[:password] == 'railsforum'
  end


[ A couple questions will raise here...
the first part helper_method :admin? make the admin? method available on the view.
the second part will default the password to 'railsforum' not the best practice this is just for learning purposes. perhaps phase 2 will be to encrypt this password or retrieve from a DB Table.
the third part for the authorize method will check for the validation of the admin? object and redirect to home_path (this does not exist yet but will be ;-) please be patient... ) in case of failure.

10.- In the projects controller file add a before_filter method to perform the authorize validation previously declared
#app/controller/projects_controller.rb

class ProjectsController < ApplicationController
  # GET /projects

To:
class ProjectsController < ApplicationController
  before_filter :authorize, :except => :index

  # GET /projects....


11.- Lets create 2 methods on the sessions controller to perform the authentication:
#app/controller/sessions_controller.rb
class SessionsController < ApplicationController

  def login
  end

  def logout
  end
end


Change to:
class SessionsController < ApplicationController

  def create
    session[:password] = params[:password]
    flash[:notice] = "Successfully logged in"
    redirect_to home_path
  end


  def destroy
    reset_session
    flash[:notice] = "Successfully logged out"
    redirect_to login_path
  end

end


12.- In order to permit our application to access the login / logout pages lets add to the routes...
#config/routes.rb
ActionController::Routing::Routes.draw do |map|
  map.resources :projects

Change to:
ActionController::Routing::Routes.draw do |map|
  map.resources :projects, :sessions
  map.home '', :controller => 'projects', :action => 'index'
  map.login 'login', :controller => 'sessions', :action => 'new'
  map.logout 'logout', :controller => 'sessions', :action => 'destroy'

This will add the :sessions controller to the resources.
Also provide a default index page (yes we still need to delete the default index page public/index.html)
With the map.login give us the url path /login or /logout and route it to the sessions controller using the appropiate action.

13.- Remove the default index.html file located at: public/index.html


14.- The last thing to do is to create the content of the /login page. [This particular trick took me a little bit to understand since is just on the view. Create a file called 'new.html.erb' just like the action described on the routes file, since we created all this on the begining just rename the file called login.html.erb to new.html.eb.
#mv app/views/sessions/login.html.erb app/views/sessions/new.html.erb

Edit the file and enter the form for the Login:

<h1>Sessions#login</h1>
<p>Find me in app/views/sessions/login.html.erb</p>

change to:
<center>
    <% form_tag sessions_path do %>
      Password <%= password_field_tag :password %>
    <% end %>
</center>

[ This is the simple login form used to authenticate ]



#app/views/sessions/logout.html.erb

<h1>Sessions#logout</h1>
<p>Find me in app/views/sessions/logout.html.erb</p>

Change to:
<center>
    <h3> Successfully Logout </h3>
</center>

15.- Everything is ready let's launch the web server

script\server

To start will show:
Listing projects
Title     Description
At this point there is no projects in the application.

Let's login:
http://127.0.0.1:3000/login

As password enter "railsforum" then hit enter... feel free to play with your projects application.

Once your are ready to leave the site go to:
http://127.0.0.1:3000/logout

Yes I know a link will be more appropiate but feel free to tweak your needs.

That's All, I hope you enjoy and learn something else today, yes there are many other ways to do it, this is just a particular solution for a very small scale requirements, but surely fits my needs ;-)

I want to thank Ryan Bates for his great work on www.railscasts.com - This tutorial is inspired in his awesome work on the videos 20-21-22. I never could learn as much about rails in a short period of time without the help & inspiration of his screencasts.. yes yes... some books, peepcode, and a lot online research...

Features:
Provide security to a RoR application with a very simple controller.
More learning about the methods in the view & the smart usage of routes.
To learn more about how everything works behind the scenes not just plugin usage ;-)

Todo:
Enable the keep an MD5 of the password instead of plain text.
Combine with previous application with Permalinks: http://www.railsforum.com/viewtopic.php?id=14236 and setup a  more complete application with authentication.
Enable a little bit more complex authentication with user/password/groups... to allow small teams to interact in a very simple way without the complexity of another table on the DB.

It's that time of the year and I will enjoy the SuperBowl from Toluca, Mexico, go Rails Go, yes Go Patriots GO!!!
Din00z.

Last edited by dinooz (2008-03-03 13:55:54)