h1. Cream This project aims to assist in setting up a Rails 3 app with an integrated Authentication and Authorization solution for your ORM of choice. Execute the *full_config* generator with arguments specifying: * The User roles in the app * The role strategy to use (both single and multiple roles for each user) * ORM to use (Relational or Document based datastores) The generator will do its magic to your app and (hopefully) you should be set to go with implementing the remainder of your app ;) Cream targets smooth integration of the following main systems: * "Devise":http://github.com/plataformatec/devise - Authentication * "CanCan":http://github.com/ryanb/cancan - Authorization * "Roles":http://github.com/kristianmandrup/roles_generic - Roles Cream also uses "CanCan permits":http://github.com/kristianmandrup/cancan-permits to enable use of *Permits* and *Licenses*. The gems "devise-links":http://github.com/kristianmandrup/devise-links and "cancan-rest-links":http://github.com/kristianmandrup/cancan-rest-links provide helpers to facilitate working with authentication links and REST links with automatic execution of user permission logic! Cream comes with a suite of specialized generators that should let you configure your Rails 3 app with these systems to a large degree. Note: Lately Cream also has options for some common customizations such as allowing login using either username or email. h2. Objectives * Integrate a set of widely accepted sub-systems for a fully integrated solution * Provide generators that can auto-configure your Rails 3 app with these systems for a given ORM h2. More info For more information see the "Cream Wiki":https://github.com/kristianmandrup/cream/wiki, which includes overviews of the: * "Roles read API":https://github.com/kristianmandrup/cream/wiki/Roles-Read-API and "Roles write API":https://github.com/kristianmandrup/cream/wiki/Roles-Read-API. * Various "Cream APIs"::https://github.com/kristianmandrup/cream/wiki (helper methods to facilitate working with Users, Sessions, Roles and Permissions). Please let me know of other areas that you think should be covered in the Wiki or on page. h2. The magic behind the curtain... Cream leverages an extensive "Tool suite":https://github.com/kristianmandrup/cream/wiki/Tool-suite-for-designing-powerful-generators-and-gems-for-Rails-3 I have created specifically to make it much easier/faster to create gems and generators for Rails 3 and spec/test them with RSpec 2, all using more natural DSLs and APIs. If you look into the Cream code you can see extensive usage of this "magic" (especially in the generators). Status (Jan 15): I'm currently in the process of refactoring and improving this underlying "tool suite". I might call it _rails-mixer_ or something :P ? h2. Cream user group The "Cream user group":http://groups.google.com/group/rails-cream is a google group where you can ask Cream related questions, provide suggestions etc. to the Cream community. h2. Inspiration and Ideas _Tony Amoyal_ has written a two part series ("Part I":http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/, "Part II":http://www.tonyamoyal.com/2010/09/29/rails-authentication-with-devise-and-cancan-part-2-restful-resources-for-administrators/) on how to setup a fully integrated Devise/CanCan solution with Roles. You might want to take a look at this for further customization needs. It might also provide food for thought for suggestions on improvements to the Cream framework ;) I have started work on a _devise:customize_ generator to facilitate some of these customization needs... Currently there is support for seting up a Guest user and and option to use both username and password as valid credentials. h3. Design ideas Please see the "Design ideas":https://github.com/kristianmandrup/cream/wiki/Design-ideas section on the wiki for possible enhancements you might want to add and/or ideas for further improvments to the framework. Feel free to add your own suggestions and ideas! Currently when the Cream config generator is given a set of roles, it both sets up the Roles creates Devise Users for all those roles. In real life scenarios, you will likely want a set of roles and a set of user types. The user types are distinct types of users, possibly with distinct data, registration pages, authentication rules (devise config) etc. The roles are more generic in nature, and users of various user types can each share one or more roles. The API should also include a DSL to easily customize this. Please also see "Cream Guest user":https://github.com/kristianmandrup/cream/wiki/Cream-Guest-user for more info on the current approach and the inherent problems with this. Example idea:
  class Editor < User
    default_role :editor
    
    valid_roles_are :publisher, blog_editor
    roles_config :multi
  end
This way, any editor user created will always be given the :editor role on creation and he can later add the :publisher and/or :blog_editor roles, depending on whether Cream is set up as a single or multi role system. In the future, the framework might even allow some user types to have multiple roles and others to have only a single role (here indicated by the _roles_config :multi_ statement) ? What do you think? *Ideas and suggestions are most welcome!* h2. Cream edge, debugging and assisting developing the framework Cream edge (directly from trunk or a feature branch), might have some extra goodies you could be interested in. To help develop Cream or use the edge version, just do: gem 'cream', :git => 'https://github.com/kristianmandrup/cream.git' There is also a _:branch_ option to use a specific branch, fx a feature branch. If you want to develop on Cream: git clone https://github.com/kristianmandrup/cream.git Optionally switch to particular branch in your local cloned repo: git checkout [feature branch] Then in your app, tell it to use your local version using the :_path_ option: gem 'cream', :path => 'path to your cloned cream' And you'll be ready to experiment, debug and add features from there :) h2. Rails 3 demo apps with Cream The following Rails 3 demo apps use Cream 0.7.7 and above and were created around Dec 1. 2010 * "Cream app with Active Record":https://github.com/kristianmandrup/cream-app-active_record * "Cream app with Mongoid":https://github.com/kristianmandrup/cream-app-mongoid * "Cream app with Mongo Mapper":https://github.com/kristianmandrup/cream-app-mongo_mapper You are most welcome to publish your own demo app with a later version of Cream. These apps need to be updated and demonstrate the real functionality of using the various APIs and DSLs that come with Cream and its supporting libs ;) h2. Authentication systems Cream targets "Devise":http://github.com/plataformatec/devise as the Authentication system of choice See "Devise Configuration options":https://github.com/kristianmandrup/cream/wiki/Devise-Configuration-options for more details on configuring your devise User models. h3. Devise links The project "devise links":http://github.com/kristianmandrup/devise-links adds more convenience for creating view links to trigger Devise session actions. h2. Authorization system There is support for the "CanCan":http://github.com/ryanb/cancan Authorization system. I have created a "Cancan permits":http://github.com/kristianmandrup/cancan-permits gem that adds the concept of Permits for each role (see below). Another framework of interest: "Aegis - The alternative Authorization solution":http://github.com/makandra/aegis h2. Roles I have developed a flexible "Roles Generic":http://github.com/kristianmandrup/roles_generic system which is used as the basis for the default Role system. The *Roles Generic API* has been implemented for the following ORMs * "Roles Active Record":http://github.com/kristianmandrup/roles_active_record * "Roles DataMapper":http://github.com/kristianmandrup/roles_data_mapper * "Roles MongoMapper":http://github.com/kristianmandrup/roles_mongo_mapper * "Roles Mongoid":http://github.com/kristianmandrup/roles_for_mongoid * "Roles Simply Stored":https://github.com/kristianmandrup/roles_simply_stored Any role system can be substituted as long as you have a method #has_role? on the user which returns true or false given a string or symbol that identifies the role. h3. Role Groups Document DBs such as *Mongo* and *Riak* are ideal for modeling a role-group hierarchical relationship. Currently Role groups are supported as class level methods on the User class using a class level in-memory hash map. See "Roles Group API":https://github.com/kristianmandrup/roles_generic/wiki/Roles-Group-API The Group API allows multiple roles to be grouped. Example: Say you have the _admin_ roles: * Admin * Super admin And the _customer_ roles * Individual customer * Company customer You might want to group them like this:
  User.add_role_group :customers => [:individual_customer, :company_customer]
  User.add_role_group :admins => [:admin, :super_admin]  
Then you can handle any user with regards to his/her role group relationship like this:
  # do this only for users in the admin role group (user has either :admin or :super_admin role) 
  current_user.is_in_group? :admins do
    ...
  end
In your views you can guard view code with Role Group conditions:
  # do this only for users in the admin role group (user has either :admin or :super_admin role) 
  for_user_in_group :customers do
    ...
  end

  # Cream 0.8.9 (edge)
  not_for_user_in_group :admins do
    ...
  end
h2. ORMs In general, it should now finally be pretty easy to set up a Rails 3 app, with a full Authentication and an Authorization system linked to a Role system using one of the following supported Cream ORMs. Relational Databases: * _Active Record_ * _Data Mapper_ Document stores: * _Mongo Mapper_ * _Mongoid_ * _Couch DB_ These ORMs are also supported for the *CanCan Permits* and *Roles* systems. h2. Installation and configuration This gem has been designed for Rails 3 and Ruby 1.9 only. Some users have notified me that it doesn't work on Ruby 1.8.7, so be advised! h3. Install gems Insert
gem 'cream'
in your Rails 3 Gemfile
$ bundle install
h2. Role system Role strategies can be set up using the "Roles Generic":http://github.com/kristianmandrup/roles_generic gem or any of the ORM specific roles gems such as "Roles Active Record":http://github.com/kristianmandrup/roles_active_record. h2. CanCan Role based authorization for "CanCan":http://github.com/ryanb/cancan can be achieved by creating a *Permit* class for each role. h3. Permits A *Permit* lets a user in a given role do certain actions as defined in the Permit. A Permit can also reuse permission logic in the form of Licenses for a more fine grained design if needed. CanCan Permits comes with generators to generate Permit files which are placed in '/app/permits'. You can then edit the Permits to suit your needs. The project "CanCan REST links":http://github.com/kristianmandrup/cancan-rest-links provides a convenient way to handle CanCan REST links, using a flexible API. Check out "Cancan permits":http://github.com/kristianmandrup/cancan-permits for more info for how to use Permits. *Cancan permits* support all the ORMs that both Devise and Roles support. h3. Permits Editor I have recently created a "Permits editor":http://github.com/kristianmandrup/permits_editor application that demonstrates how you can let the user edit the Permits, Licenses and even individual User permissions directly as part of an admin section of the web app. The *Permits editor* updates yaml files that are now part of the *cancan-permits* infrastructure (if present and registered). I plan to refactor the Permits Editor into a "mountable app":http://piotrsarnacki.com/2010/12/21/mountable-apps-tutorial/ when I have the time. h3. Licenses For more advanced authorization scenarios you can create reusable permission logic in license classed that are placed in '/app/licenses/'. A License can be reused in multiple Permits. See "CanCan permits demo app":https://github.com/kristianmandrup/cancan-permits-demo for an example of how to use cancan-permits and licenses. h2. Role specific Customization of Routing and User classes Please see "Customizing Routes and User classes for Roles":https://github.com/kristianmandrup/cream/wiki/Customizing-Routes-and-User-classes-for-Roles The generator now generates initial Routes configuration for each role in order to facilitate Registration page customization for each role if needed. A User subclass is now generated for each role by default in order to allow more User customization and for the above mentioned routing customization to function. h2. Generators Please see "Cream generators overview and walk-through":https://github.com/kristianmandrup/cream/wiki/Cream-generators-overview-and-walk-through for more details. The following generators are currently available: Main generator: * cream:full_config - Configure Rails 3 application with Cream (master generator) Config generators: Devise (authentication) * _devise:config_ - Configure Rails 3 application with Devise * _devise:users_ - Configure Rails 3 application with Devise users * _devise:customize_ - Customize devise configuration Authorization incl. roles * _cancan:config_ - Configures app with CanCan * _permits:config_ - Configures app with CanCan Permits * _roles:config_ - Configures app with Roles Other generators: * _cancan:restlinks_ - Create REST links locale file * _devise:links_ - Create devise links locale file (should I rename this to authlinks?) * _cream:views_ - Generates partials for menu items (outdated) All the above generators have specs included in cream that demonstrate how to use them and should verify that they work as expected. The *cream:full_config* generator should call all the sub-generators in succession to fully configure the Rails 3 app according to your preferences. h3. Full Config Generator Master cream generator which calls the sub-generators in succession. * strategy : role strategy to use (see *roles_generic* gem) * orm : orm to be used * roles : list of valid roles and permits to use Example: rails g cream:full_config --strategy admin_flag --orm AR By default creates :guest and :admin roles. h2. Sub generators To view the run options of any of the sub generators, simply type $ rails g [GENERATOR_NAME] Example: rails g permits:config h3. Cream Views Generator Moves 'user menu' partials views into app/views/_user_menu rails g cream:views [scope] [--haml] * (scope) : The scope/namespace folder under views to copy the partials to, 'cream' is the default * (haml) : Use HAML as template language (default is erb) The *views* generator is based on a similar generator from the devise project. The Views generator and partials have been updated (Jan 6, 2011). The partials generated are useful for creating menu items for login/logout and registration. The links are automatically displayed or hidden depending on the current state of the user. h2. Note on Patches/Pull Requests * Fork the project. * Make your feature addition or bug fix. * Add tests for it. This is important so I don't break it in a future version unintentionally. * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) * Send me a pull request. Bonus points for topic branches. h2. Copyright Copyright (c) 2010 Kristian Mandrup. See LICENSE for details.