Index by title

Work in Progress for upcoming 0.7.0 release

Lockdown

What

Lockdown is a authentication/authorization system for RubyOnRails (ver 2.x). Here's a quick summary of Lockdown:

A permission can consist of any combination of controllers and actions, more about this later.

A UserGroup consists of a collection of permissions.

This allows you manage the security of your application in one place. No before_filters scattered in your controllers.

If you are interested in using Lockdown for another Ruby framework, please let me know.

Please use either memcache or the database session store instead of the default cookie session store. Due to the current implementation of access_right storage, the size limitations for the cookie may become an issue for larger projects.

Installing

$ sudo gem install lockdown
$ cd <your_project_directory>
$ ./script/generate lockdown
This will give you the following output:
stonean@local ~/Sites/test $ ./script/generate lockdown
      exists  app/views
      exists  app/controllers
      exists  app/helpers
      create  lib/lockdown
      create  lib/lockdown/session.rb
      create  lib/lockdown/init.rb
      create  app/views/users
      create  app/views/user_groups
      create  app/views/permissions
      create  app/controllers/permissions_controller.rb
      create  app/helpers/permissions_helper.rb
      create  app/controllers/users_controller.rb
      create  app/helpers/users_helper.rb
      create  app/controllers/user_groups_controller.rb
      create  app/helpers/user_groups_helper.rb
      create  app/views/users/index.html.erb
      create  app/views/users/show.html.erb
      create  app/views/users/edit.html.erb
      create  app/views/users/new.html.erb
      create  app/views/user_groups/index.html.erb
      create  app/views/user_groups/show.html.erb
      create  app/views/user_groups/edit.html.erb
      create  app/views/user_groups/new.html.erb
      create  app/views/permissions/index.html.erb
      create  app/views/permissions/show.html.erb
      create  app/views/sessions
      create  app/controllers/sessions_controller.rb
      create  app/views/sessions/new.html.erb
      exists  app/models
      create  app/models/permission.rb
      create  app/models/user.rb
      create  app/models/user_group.rb
      create  app/models/profile.rb
      create  db/migrate
      create  db/migrate/20090104011604_create_profiles.rb
      exists  db/migrate
      create  db/migrate/20090104011605_create_users.rb
      exists  db/migrate
      create  db/migrate/20090104011606_create_user_groups.rb
      exists  db/migrate
      create  db/migrate/20090104011607_create_permissions.rb
      exists  db/migrate
      create  db/migrate/20090104011608_create_admin_user.rb

As you can see, this will create a "lockdown" directory in the lib dir add two files: init.rb and session.rb.
Modify init.rb to set configuration options and define the permissions and user groups that apply to your system.

Please keep the following in mind:

Why? Simply because creating User Groups via the administration screens will only add more work for you if you want to run tests using those groups.

Please refer to the lockdown generator page for more detail on the generator and the files it creates.

How it works

When the Lockdown generator is run, it adds the necessary config.gem line in your environment.rb.

As your application starts and your environment.rb is 'executed' the config.gem 'lockdown' statement will require Lockdown. When Lockdown is required, it will in turn require your lib/lockdown/init.b and start parsing your rules.

This is the default init.rb included with Lockdown:

require "lockdown" 
require File.join(File.dirname(__FILE__), "session")

Lockdown::System.configure do

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Configuration Options
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Options with defaults:
  #
  # Set timeout to 1 hour:
  #       options[:session_timeout] = (60 * 60)
  #
  # Call method when timeout occurs (method must be callable by controller):
  #       options[:session_timeout_method] = :clear_session_values
  #
  # Set system to logout if unauthorized access is attempted:
  #       options[:logout_on_access_violation] = false
  #
  # Set redirect to path on unauthorized access attempt:
  #       options[:access_denied_path] = "/" 
  #
  # Set redirect to path on successful login:
  #       options[:successful_login_path] = "/" 
  #
  # If deploying to a subdirectory, set that here. Defaults to nil
  #       options[:subdirectory] = "blog" 
  #       * Notice: I'm still working out the details on this one.
  #       * Do not add leading or trailing slashes
  #
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Define permissions
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
  # set_permission(:product_management, all_methods(:products))
  #
  # :product_management is the name of the permission which is later
  # referenced by the set_user_group method
  #
  # :all_methods(:products) will return an array of all controller actions
  # for the products controller
  #
  # if products is your standard RESTful resource you'll get:
  #   ["products/index , "products/show",
  #    "products/new", "products/edit",
  #    "products/create", "products/update",
  #    "products/destroy"]
  #
  # You can pass multiple parameters to concat permissions such as:
  #      
  #      set_permission(:security_management,all_methods(:users),
  #                                       all_methods(:user_groups),
  #                                       all_methods(:permissions) )
  #
  # In addition to all_methods(:controller) there are:
  #
  #       only_methods(:controller, :only_method_1, :only_method_2)
  #
  #       all_except_methods(:controller, :except_method_1, :except_method_2)
  #
  # Some other sample permissions:
  # 
  #  set_permission(:sessions, all_methods(:sessions))
  #  set_permission(:my_account, only_methods(:users, :edit, :update, :show))
  # 
  # Define your permissions here:

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Built-in user groups
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #  You can assign the above permission to one of the built-in user groups
  #  by using the following:
  # 
  #  To allow public access on the permissions :sessions and :home:
  #    set_public_access :sessions, :home
  #     
  #  Restrict :my_account access to only authenticated users:
  #    set_protected_access :my_account
  #
  # Define the built-in user groups here:

  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # Define user groups
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #
  #  set_user_group(:catalog_management, :category_management, 
  #                                      :product_management) 
  #
  #  :catalog_management is the name of the user group
  #  :category_management and :product_management refer to permission names
  #
  # 
  # Define your user groups here:

end 

As you can see, the first line requires lockdown. This will load the Lockdown system which consists of various parts:

When referring to access rights: if you have a standard REST users controller, the access rights would be:

  users/index
  users/show
  users/edit
  users/update
  users/new
  users/create
  users/destroy

The internals

All configuration of Lockdown (Permissions and User Groups) are done in lib/lockdown/init.rb. The database functionality is merely an extension of the definitions to allow for the dynamic creation of User Groups. Permissions can not be created via the administration screens.

Lockdown doesn't have a concept of Roles. Instead, Lockdown users can be associated to one or many User Groups to allow for flexibility. In addition, you can use the admin screens to add new User Groups to the database. User groups are nothing more than a grouping mechanism for Permissions to ease management.

Here are the parts to Lockdown:

Roadmap to 1.0

**this is tentative and the feature order may change

Github

http://github.com/stonean/lockdown/tree/master

clone url: git://github.com/stonean/lockdown.git

Contact

Please use the forum to ask questions and the issue tracker to report problems or submit a pull request.

License

This code is free to use under the terms of the MIT license.

Copyright (c) 2008 Andrew Stone


Lockdown Generator

What

This page will describe how to get started with a new application.

There are now generator options to give you more control over which templates you want to mix-in to your application:

*--all is now the default option*

Creating a new application

$ rails demo_app
<snip output>
$ cd demo_app
$ lockdown .
------------------------------------------------------------
Installing Lockdown
      create  lib/lockdown
      create  lib/lockdown/session.rb
      create  lib/lockdown/init.rb
------------------------------------------------------------

------------------------------------------------------------
Modified config/environment.rb by adding:
    require "lockdown/init" 
------------------------------------------------------------

------------------------------------------------------------
You are now locked down.  To open up access to your application 
please modify lib/lockdown/init.rb.  This is where you'll 
add permissions and create user groups.

To modify the contents of your session and to add access 
methods, modify lib/lockdown/session.rb.

If you want to know more, please visit:

http://lockdown.rubyforge.org

If you have any suggestions, comments or issues 
please visit the Lockdown Google group:

http://groups.google.com/group/stonean_lockdown?hl=en
------------------------------------------------------------

Now it's time to get the template...

$ ./script/generate lockdown --all
      exists  app/helpers
      exists  app/models
      exists  app/views
      create  app/views/users
      create  app/views/user_groups
      create  app/views/permissions
      create  app/views/sessions
      exists  app/controllers
      create  app/controllers/permissions_controller.rb
      create  app/controllers/users_controller.rb
      create  app/controllers/user_groups_controller.rb
      create  app/controllers/sessions_controller.rb
      create  app/models/permission.rb
      create  app/models/user.rb
      create  app/models/user_group.rb
      create  app/models/profile.rb
       route  map.resources :permissions
       route  map.resources :user_groups
       route  map.resources :users
       route  map.resources :sessions
      create  app/helpers/permissions_helper.rb
      create  app/helpers/users_helper.rb
      create  app/helpers/user_groups_helper.rb
      create  app/views/users/_data.html.erb
      create  app/views/users/_form.html.erb
      create  app/views/users/index.html.erb
      create  app/views/users/show.html.erb
      create  app/views/users/edit.html.erb
      create  app/views/users/new.html.erb
      create  app/views/users/_password.html.erb
      create  app/views/user_groups/_data.html.erb
      create  app/views/user_groups/_form.html.erb
      create  app/views/user_groups/index.html.erb
      create  app/views/user_groups/show.html.erb
      create  app/views/user_groups/edit.html.erb
      create  app/views/user_groups/new.html.erb
      create  app/views/permissions/_data.html.erb
      create  app/views/permissions/index.html.erb
      create  app/views/permissions/show.html.erb
      create  app/views/sessions/new.html.erb
      create  db/migrate
      create  db/migrate/001_create_profiles.rb
      exists  db/migrate
      create  db/migrate/002_create_users.rb
      exists  db/migrate
      create  db/migrate/003_create_user_groups.rb
      exists  db/migrate
      create  db/migrate/004_create_permissions.rb
      exists  db/migrate
      create  db/migrate/005_create_admin_user_and_user_group.rb

Run your migrations:

$ rake db:migrate --trace

Remove index.html

$ rm public/index.html

Start the app and then open up your browser to http://localhost:3000

$ ./script/server

You'll see that the "lockdown --all" generator has added a default route to the login page.

Login using the basic admin account with credentials: admin/password

After you login (you'll still be on the login page), go one of the following pages:

http://localhost:3000/users

http://localhost:3000/user_groups

There is a permissiosn page also available, but you don't have any with the basic install. And since permissions cannot be created via the admin screens, this doesn't have much value for you now.

http://localhost:3000/permissions

Permissions

Alright, so there's not a lot to see on these basic screens but that's only because there's isn't a lot to the system at the moment.

Now it's time to look at lib/lockdown/init.rb. Open it in your favorite editor.

There's some documentation with examples that will hopefully server for more than a reminder. Please read that documentation before continuing here.

...

I guess that wasn't sufficient? If you don't understand how to use init.rb, please post a question on the forum and I'll address the issue there and then update init.rb.

For simplicity sake, I would like the documentation for init.rb contained within that file.

Contact

Comments and suggestions are welcome via the forum: http://stonean.com/projects/lockdown/boards