August 9, 2011 – Announcement!
During the past few months, @kristianmandrup and @stanislaw have been working hard to come up with a replacement for cream, redesigning the core components from the ground up, with a full spec suite, dummy apps for integration testing etc.
The fruits are now ready to be harvested! Today we announce the Release Candidate
The gem (with Rails 3 engine) will be released later today when we have the wiki and README in place ;)
Also join the CanTango discussion group
We hope you will enjoy it and join in the effort to create a super ACM system for Rails 3 :)
PS: This also means that cream will no longer be maintained. All efforts are now on CanTango. Please migrate from cream to CanTango.
A migration guide will be available on the wiki soon.
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 types in the application (for Authentication, route Authorization and User data)
- The User roles in the app (for fine-grained Authorization)
- The main Role strategy to use (allow single or multiple roles for each user)
- ORM to use (Relational and Document based datastores are supported – see below)
The cream generator will apply all its “magic” to your app so you can implement your permission business logic using intuitive APIs.
Cream targets smooth integration of the following main systems:
- Devise – Users and Authentication
- CanCan – Authorization of users
- Roles – Roles and role groups for authorization
Cream comes with a suite of specialized generators that aim to facilitate configuration of your Rails 3 app with these systems. For details on how to use these generators, please see the documentation for the individual gem.
Status update (June 22, 2011)
During most of May and June (2011), the cream gem has been broken due to an update of the gem ‘sugar-high’, which the generators depend on for file operations via the ‘file_mutate’ pack. The latest release of sugar-high, version ‘0.4.6.4’ should now ensure that the file_mutate pack is backwards compatible so that this should no longer cause an error.
I am currently working on a new framework ‘dancing tango with troles’ taking what I’ve learned so far and providing a far better solution which incorporates use of multiple user accounts for a given user and thus that a user can be logged into multiple applications simultaneously in different roles!
Please help out on this project if you find it useful! Thanks!
Status update (June 12, 2011)
Please check out the rails_3_1 branch. I’ve just added support for the File.mutat_ext :all macro available from the gem sugar-high
Cream might currently have a few gotchas to get it working (not tested since mid May). For the roles part you can substitute roles_generic with the new gem troles, which has a much cleaner design and also supports role groups. Cream will be redesigned and rebranded
as Dancing over the summer, and will support Rails 3.1. Stay tuned. You are as always most welcome to assist in the project :)
Installation and configuration
The cream gem has been designed for Rails 3 and Ruby 1.9 only.
gem ‘cream’in your Rails 3 Gemfile
$ bundle install
- Active Record
- Data Mapper
- Mongo Mapper
- Couch DB
Note: Couch DB support will soon be migrated to use CouchRest
For more information:
Please let me know of other areas that you think should be covered in the Wiki or on page.
One or more tutorials with demo applications are planned for the near future.
How to start with Cream
Cream integrates so many moving parts that running the full generator to generate all the bells and whistles and start playing around might be overwhelming for most.
I therefore recommend that you start out by experimenting with the main parts and get a feel for how to design the users/roles/permits parts of your application.
1) Devise user with Roles
2) Cancan permits
3) User types
First I would generate a single Devise user and then run Roles for the ORM you are using. Then play around with the Roles API to get a feel for it.
Later You can run the cancan-permits generator and play around with permissions, using permits and licenses to get a feel for this API and how it plays with the roles.
Then think about which user types you need. User types are distinct types of users that might have individual data needs (separate table or schema), individual registration pages or different administration rules (devise strategies such as email confirmation etc.)
Then decide which roles should be available for each user type_, that is what kind of usertype each role makes sense for. You might also decide to group multiple roles into role groups.
Roles: super admin, forum admin, guest user, normal user, content publisher
In this scenario it would make sense to have these User types: User, Guest, Admin
The user types should make roles available as follows:
- Guest: guest
- User: normal, content_publisher
- Admin: super_admin, forum_admin
This is done via the method valid_roles_are (see the Roles API).
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
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 ;)
I plan to release new demo apps for the 0.9 version of Cream in May, 2011
Sub systems of Cream
Cream targets Devise as the Authentication system of choice
See Devise Configuration options for more details on configuring your devise User models.
The project devise links adds more convenience for creating view links to trigger Devise session actions.
The Roles system is based on Roles Generic, a generic Roles API implementation where parts are overriden by Roles implementations for specific ORMs.
The Roles Generic API has been implemented for the following ORMs
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.
You can also use Role groups to group multiple roles into a group and query if a user has any of the roles in the group.
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 provides a convenient way to handle CanCan REST links, using a flexible API.
Check out Cancan permits for more info for how to use Permits.
Cancan permits support all the ORMs that both Devise and Roles support.
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 for an example of how to use cancan-permits and licenses.
I have recently created a 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 when I have the time.
Please see Cream generators overview for more details on generators including objectives and what each generator aims to produce (update your app with).
The following generators are currently available with Cream:
Main app generator:
- cream:full_config – Configure Rails 3 application with Cream (master generator)
Individual configuration generators:
The following generators can all be used individually.
- 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
- 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
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.
Full Config Generator
rails g cream:full_config --strategy admin_flag --orm AR
By default creates :guest and :admin User types.
To view the run options of any of the sub generators, simply type $ rails g [GENERATOR_NAME]
rails g permits:config
Cream Views Generator
Moves ‘user menu’ view partials into app/views/cream
rails g cream:views [scope] [--haml]
- (scope) : The scope/namespace folder under views to copy the partials to, ‘cream’ is the default scope (namespace)
- (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.
Inspiration and Ideas
Tony Amoyal has written a two part series (Part I, Part II) 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.
The magic behind the curtain
Cream leverages an extensive Tool suite that 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, using more natural DSLs and APIs.
If you look into the Cream code you can see extensive usage of this.
The path towards 1.0
Since cream version 0.9.2, the project should be pretty stable again. I plan to release a 1.0 release of Cream and all gems it uses when I have checked that they all work as they should with the latest versions of Rails, Devise and CanCan. The 1.0 version will also come with a full step-by-step tutorial for both a simple case (1 user type where each user can have only 1 role) and a more advanced scenario (multiple user types where some users can have multiple roles).
Cream 2 will be a total redesign/refactoring using what I have learned and will be inspired by Jose Valim’s book Crafting Rails Applications.
I will create a new project using enginex, complete with one or more dummy apllications and take it from there. Sadly I will likely not have time for this until April 2011, so if anyone has the time and energy, please help me in this effort!
Cream edge, debugging and how to assist in 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 :)
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.
Copyright © 2010 Kristian Mandrup. See LICENSE for details.