coffeeaddict/kindergarten

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# Kindergarten

[![Build Status](https://secure.travis-ci.org/coffeeaddict/kindergarten.png)](http://travis-ci.org/coffeeaddict/kindergarten)

[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/coffeeaddict/kindergarten)

A way to achieve modularity and modular security with a sandbox on steroids.

## Introduction

### Modules
A Kindergarten could be seen as collection of service objects, each
representing a 'play area' (think: doll area, lego table, etc. etc.).

Within the realm of kindergarten, the service objects are refered to as
modules.

### Sandboxing
The modules are plugged into the kindergarten and can be governed, both per
module and kindergarten wide. There are governesses looking for, and preventing
trouble.

Each module is not just exposed as-is; it is sandboxed. Which means that they
must specify which methods are to be played with.

### Child
What good would a kindergarten with a sandbox full of toys be without a child?
In a Rails context; the most logical choise for a child would be
the ```current_user```.

## Installation

Add this line to your application's Gemfile:

    gem 'kindergarten'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install kindergarten

## Usage

```ruby
  # define a child
  child = User.find(2)

  # define a module (perimeter) for the child to play in
  class MyPlayModule < Kindergarten::Perimeter
    # every module must have a purpose.
    # The purpose also serves as a namespace
    #
    purpose :playing

    # use can-can rules to govern the perimeter
    govern do
      can :watch, Television
      cannot :watch, CableTV

      can :eat, Candy do |candy|
        child.quotum.allows(candy)
      end
    end

    # define exposed methods
    expose :watch_tv, :eat

    def watch_tv(tv)
      guard(:watch, tv)
      child.watch(tv)

      sleep(:four)
    end

    def eat(candy)
      guard(:eat, candy)
      child.eat(candy)
    end

    def sleep(len) # not_accessible_from_outside
      child.sleep(len)
    end

    # or expose methods in an 'annotation like way'

    expose :method
    # method that does nothing at all
    def method
    end
  end

  # load the child (any object) and the module into a sandbox
  sandbox = Kindergarten.sandbox(child)
  sandbox.load_module(MyPlayPerimeter)

  # you can now call the sandboxed methods on the sandbox
  sandbox.playing.watch_tv(CableTV.new)   # fails with Kindergarten::AccessDenied
  30.times do
    sandbox.playing.eat(Liquorice.new)    # fails after a while
  end

  sandbox.playing.sleep(:long)            # fails with NoMethodError

  sandbox.allows?(:watch, Television)
  # => true
```

You are not restricted to only one perimeter/module - that would be most
boring...

Infact, the above is the essence of things - but there is much much more fun
hidden inside the Kindergarten. More will follow on the Wiki

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request