kindergarten 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +9 -0
- data/Gemfile +17 -2
- data/README.md +1 -1
- data/TODO.md +11 -3
- data/kindergarten.gemspec +5 -4
- data/lib/kindergarten.rb +3 -2
- data/lib/kindergarten/exceptions.rb +36 -1
- data/lib/kindergarten/governesses/head_governess.rb +2 -1
- data/lib/kindergarten/perimeter.rb +27 -27
- data/lib/kindergarten/purpose.rb +41 -0
- data/lib/kindergarten/sandbox.rb +29 -15
- data/lib/kindergarten/version.rb +1 -1
- data/spec/kindergarten/governess_spec.rb +8 -8
- data/spec/kindergarten/perimeter_spec.rb +31 -28
- data/spec/kindergarten/sandbox_spec.rb +38 -4
- data/spec/orm/active_record_spec.rb +30 -30
- data/spec/orm_helper.rb +7 -4
- data/spec/support/dining_perimeter.rb +5 -3
- data/spec/support/drinking_perimeter.rb +11 -9
- data/spec/support/methodless_module.rb +3 -0
- data/spec/support/puppet_perimeter.rb +4 -2
- data/spec/support/purposeless_module.rb +7 -0
- data/spec/support/spec_perimeter.rb +3 -1
- metadata +34 -20
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,4 +1,19 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
#
|
4
|
-
|
3
|
+
# for travis, use a real gemfile
|
4
|
+
gem "cancan", "~> 1.6.8"
|
5
|
+
gem "activesupport", "> 3"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "bundler", "~> 1.2"
|
9
|
+
gem "rake"
|
10
|
+
gem "rspec", '~> 2.11'
|
11
|
+
gem "activerecord", "> 3"
|
12
|
+
platforms :jruby do
|
13
|
+
gem 'jdbc-mysql'
|
14
|
+
gem 'activerecord-jdbcmysql-adapter'
|
15
|
+
end
|
16
|
+
platforms :ruby do
|
17
|
+
gem 'mysql2', :git => "git://github.com/brianmario/mysql2.git"
|
18
|
+
end
|
19
|
+
end
|
data/README.md
CHANGED
@@ -29,7 +29,7 @@ child = User.find(2)
|
|
29
29
|
# define a module (perimeter) for the child to play in
|
30
30
|
class MyPlayModule < Kindergarten::Perimeter
|
31
31
|
# use can-can rules to govern the perimeter
|
32
|
-
govern do
|
32
|
+
govern do
|
33
33
|
can :watch, Television
|
34
34
|
cannot :watch, CableTV
|
35
35
|
|
data/TODO.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
# Kindergarten TODO
|
2
2
|
|
3
|
-
##
|
3
|
+
## Code
|
4
4
|
|
5
|
-
*
|
6
|
-
|
5
|
+
* Further implement ```sandbox.projects.all``` -> ```sandbox.$purpose.$method```
|
6
|
+
|
7
|
+
## Documentation
|
8
|
+
|
9
|
+
* Write more YARD docs
|
10
|
+
* Provide better insight into governess hierarchy
|
11
|
+
|
12
|
+
## Wiki
|
13
|
+
|
14
|
+
* Write some wiki pages based on the presentation
|
data/kindergarten.gemspec
CHANGED
@@ -16,10 +16,11 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Kindergarten::VERSION
|
17
17
|
|
18
18
|
gem.add_dependency('cancan', ['~> 1.6.8'])
|
19
|
-
gem.add_dependency('activesupport', ['
|
19
|
+
gem.add_dependency('activesupport', ['> 3'])
|
20
20
|
|
21
21
|
gem.add_development_dependency('rake')
|
22
|
-
gem.add_development_dependency('rspec', ['~> 2.
|
23
|
-
gem.add_development_dependency('activerecord', ['
|
24
|
-
gem.add_development_dependency('
|
22
|
+
gem.add_development_dependency('rspec', ['~> 2.11'])
|
23
|
+
gem.add_development_dependency('activerecord', ['> 3'])
|
24
|
+
gem.add_development_dependency('mysql2')
|
25
|
+
gem.add_development_dependency('jdbc-mysql')
|
25
26
|
end
|
data/lib/kindergarten.rb
CHANGED
@@ -3,9 +3,10 @@ require 'active_support/core_ext'
|
|
3
3
|
|
4
4
|
require "kindergarten/version"
|
5
5
|
require "kindergarten/sandbox"
|
6
|
-
require "kindergarten/
|
7
|
-
require "kindergarten/governesses"
|
6
|
+
require "kindergarten/purpose"
|
8
7
|
require "kindergarten/perimeter"
|
8
|
+
require "kindergarten/governesses"
|
9
|
+
require "kindergarten/exceptions"
|
9
10
|
|
10
11
|
module Kindergarten
|
11
12
|
class << self
|
@@ -12,8 +12,43 @@ module Kindergarten
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
class Sandbox
|
16
|
+
class NoPurposeError < NoMethodError
|
17
|
+
def initialize(purpose, sandbox)
|
18
|
+
@purpose = purpose
|
19
|
+
@sandbox = sandbox
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"undefined purpose '#{@purpose}' for #{@sandbox}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
15
28
|
class Perimeter
|
16
|
-
|
29
|
+
class NoExposedMethods < NoMethodError
|
30
|
+
def initialize(perimeter)
|
31
|
+
@perimeter = perimeter
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"The module #{@perimeter.name} does not expose any methods."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class NoPurpose < ArgumentError
|
41
|
+
def initialize(perimeter)
|
42
|
+
@perimeter = perimeter
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
"The module #{@perimeter.name} does not have a purpose."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Signals bad sandbox method implementation
|
17
52
|
class Unguarded < SecurityError; end
|
18
53
|
end
|
19
54
|
end
|
@@ -4,6 +4,7 @@ module Kindergarten
|
|
4
4
|
#
|
5
5
|
class HeadGoverness
|
6
6
|
include CanCan::Ability
|
7
|
+
attr_reader :child
|
7
8
|
|
8
9
|
def initialize(child)
|
9
10
|
@child = child
|
@@ -130,7 +131,7 @@ module Kindergarten
|
|
130
131
|
untaint = untaint_opts[key]
|
131
132
|
next if untaint == :pass
|
132
133
|
|
133
|
-
match = value.match(untaint)
|
134
|
+
match = "#{value}".match(untaint)
|
134
135
|
if match.nil?
|
135
136
|
scrubbed.delete key
|
136
137
|
else
|
@@ -5,7 +5,7 @@ module Kindergarten
|
|
5
5
|
# class ExamplePerimeter < Kindergarten::Perimeter
|
6
6
|
# purpose :books
|
7
7
|
#
|
8
|
-
# govern do
|
8
|
+
# govern do
|
9
9
|
# can :read, Book do |book|
|
10
10
|
# book.level <= 2
|
11
11
|
# end
|
@@ -21,13 +21,29 @@ module Kindergarten
|
|
21
21
|
#
|
22
22
|
class Perimeter
|
23
23
|
class << self
|
24
|
-
attr_reader :
|
24
|
+
attr_reader :exposed_methods, :govern_proc
|
25
25
|
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
# Defines a list of sandboxed methods
|
27
|
+
#
|
28
|
+
# Can be called multiple times to grow the list.
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# class BondModule < Kindergarten::Perimeter
|
32
|
+
# # ...
|
33
|
+
# expose :m, :q
|
34
|
+
#
|
35
|
+
# # ...
|
36
|
+
# expose :enemies
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# BondModule.exposed_methods
|
40
|
+
# => [ :m, :q, :enemies ]
|
41
|
+
#
|
42
|
+
def expose(*list)
|
43
|
+
@exposed_methods ||= []
|
44
|
+
@exposed_methods |= list
|
30
45
|
end
|
46
|
+
alias_method :sandbox, :expose
|
31
47
|
|
32
48
|
# Instruct the Governess how to govern this perimeter
|
33
49
|
def govern(&proc)
|
@@ -88,31 +104,15 @@ module Kindergarten
|
|
88
104
|
end
|
89
105
|
end
|
90
106
|
|
107
|
+
delegate :scrub, :rinse, :guard, :unguarded,
|
108
|
+
:to => :governess
|
109
|
+
|
91
110
|
# @return [Array] List of sandbox methods
|
92
111
|
def sandbox_methods
|
93
|
-
self.class.
|
94
|
-
end
|
95
|
-
|
96
|
-
# @see Governess#scrub
|
97
|
-
def scrub(*args)
|
98
|
-
self.governess.scrub(*args)
|
99
|
-
end
|
100
|
-
|
101
|
-
# @see Governess#rinse
|
102
|
-
def rinse(*args)
|
103
|
-
self.governess.rinse(*args)
|
104
|
-
end
|
105
|
-
|
106
|
-
# @see Governess#guard
|
107
|
-
def guard(action, target)
|
108
|
-
self.governess.guard(action, target)
|
109
|
-
end
|
110
|
-
|
111
|
-
# @see Governess#unguarded
|
112
|
-
def unguarded(&block)
|
113
|
-
self.governess.unguarded(&block)
|
112
|
+
self.class.exposed_methods
|
114
113
|
end
|
115
114
|
|
115
|
+
# Perform a block under the watchful eye off the governess
|
116
116
|
def governed(method, unguarded=false, &block)
|
117
117
|
if unguarded == true
|
118
118
|
self.governess.unguarded do
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Kindergarten
|
2
|
+
# Keep track of a single purpose
|
3
|
+
class Purpose
|
4
|
+
attr_reader :name, :methods, :sandbox, :subscriptions
|
5
|
+
|
6
|
+
def initialize(name, sandbox)
|
7
|
+
@name = name
|
8
|
+
@sandbox = sandbox
|
9
|
+
@methods = {}
|
10
|
+
@subscriptions = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_perimeter(perimeter, instance)
|
14
|
+
if perimeter.exposed_methods.blank?
|
15
|
+
raise Kindergarten::Perimeter::NoExposedMethods.new(perimeter)
|
16
|
+
end
|
17
|
+
|
18
|
+
perimeter.exposed_methods.each do |name|
|
19
|
+
if @methods.has_key?(name)
|
20
|
+
warn "WARNING: overriding already sandboxed method #{@name}.#{name}"
|
21
|
+
end
|
22
|
+
|
23
|
+
@methods[name] = instance
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(name, *args, &block)
|
28
|
+
super
|
29
|
+
|
30
|
+
rescue NoMethodError => ex
|
31
|
+
unless methods.has_key?(name)
|
32
|
+
raise ex
|
33
|
+
end
|
34
|
+
|
35
|
+
perimeter = methods[name]
|
36
|
+
perimeter.governed(name, sandbox.unguarded?) do
|
37
|
+
perimeter.send(name, *args, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/kindergarten/sandbox.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module Kindergarten
|
2
2
|
class Sandbox
|
3
|
-
attr_reader :child, :governess, :perimeter
|
3
|
+
attr_reader :child, :governess, :perimeter, :purpose
|
4
4
|
|
5
5
|
def initialize(child)
|
6
6
|
@child = child
|
7
7
|
@governess = Kindergarten::HeadGoverness.new(child)
|
8
8
|
|
9
|
-
@
|
9
|
+
@purpose = {}
|
10
|
+
@perimeter = []
|
10
11
|
def @perimeter.include?(other)
|
11
12
|
(self.collect(&:class) & [ other.class ]).any?
|
12
13
|
end
|
@@ -25,50 +26,63 @@ module Kindergarten
|
|
25
26
|
|
26
27
|
perimeter = perimeter_class.new(child, governess)
|
27
28
|
|
29
|
+
raise ArgumentError.new(
|
30
|
+
"Module must inherit from Kindergarten::Perimeter"
|
31
|
+
) unless perimeter.kind_of?(Kindergarten::Perimeter)
|
32
|
+
|
33
|
+
self.extend_purpose(perimeter.class, perimeter)
|
34
|
+
|
28
35
|
# the head governess must know all the rules
|
29
36
|
unless governess == self.governess || perimeter_class.govern_proc.nil?
|
30
37
|
self.governess.instance_eval(&perimeter_class.govern_proc)
|
31
38
|
end
|
32
39
|
|
33
|
-
raise ArgumentError.new(
|
34
|
-
"Module must inherit from Kindergarten::Perimeter"
|
35
|
-
) unless perimeter.kind_of?(Kindergarten::Perimeter)
|
36
|
-
|
37
40
|
@perimeter << perimeter unless @perimeter.include?(perimeter)
|
38
41
|
end
|
39
42
|
end
|
40
43
|
alias_method :load_perimeter, :extend_perimeter
|
41
44
|
alias_method :load_module, :extend_perimeter
|
42
45
|
|
46
|
+
def extend_purpose(perimeter, instance)
|
47
|
+
name = perimeter.purpose || raise(
|
48
|
+
Kindergarten::Perimeter::NoPurpose.new(perimeter)
|
49
|
+
)
|
50
|
+
name = name.to_sym
|
51
|
+
|
52
|
+
self.purpose[name] ||= Kindergarten::Purpose.new(name, self)
|
53
|
+
self.purpose[name].add_perimeter(perimeter, instance)
|
54
|
+
end
|
55
|
+
|
43
56
|
def unguarded(&block)
|
44
57
|
@unguarded = true
|
45
58
|
yield
|
46
59
|
@unguarded = false
|
47
60
|
end
|
48
61
|
|
62
|
+
def unguarded?
|
63
|
+
@unguarded == true ? true : false
|
64
|
+
end
|
65
|
+
|
49
66
|
def allows?(action, target)
|
50
67
|
governess.can?(action, target)
|
51
68
|
end
|
52
69
|
alias_method :allowed?, :allows?
|
53
|
-
|
70
|
+
|
54
71
|
def disallows?(action, target)
|
55
72
|
governess.cannot?(action, target)
|
56
73
|
end
|
57
74
|
alias_method :disallowed?, :disallows?
|
58
75
|
|
76
|
+
# TODO: Find a purpose and call that - move this block to Purpose
|
59
77
|
def method_missing(name, *args, &block)
|
60
78
|
super
|
79
|
+
|
61
80
|
rescue NoMethodError => ex
|
62
|
-
|
63
|
-
|
64
|
-
return perimeter.governed(name, @unguarded) do
|
65
|
-
perimeter.send(name, *args, &block)
|
66
|
-
end
|
67
|
-
end
|
81
|
+
unless purpose.has_key?(name)
|
82
|
+
raise Kindergarten::Sandbox::NoPurposeError.new(name, self)
|
68
83
|
end
|
69
84
|
|
70
|
-
|
71
|
-
raise ex
|
85
|
+
return purpose[name]
|
72
86
|
end
|
73
87
|
end
|
74
88
|
end
|
data/lib/kindergarten/version.rb
CHANGED
@@ -27,22 +27,22 @@ describe Kindergarten::HeadGoverness do
|
|
27
27
|
|
28
28
|
describe :washing do
|
29
29
|
it "should scrub attributes" do
|
30
|
-
attr = { a
|
30
|
+
attr = { :a => 1, :b => 2, :c => 3 }
|
31
31
|
|
32
32
|
scrubbed = @governess.scrub(attr, :a, :c)
|
33
33
|
scrubbed.should_not be_has_key(:b)
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should return a ScrubbedHash after scrubbing" do
|
37
|
-
attr = { a
|
37
|
+
attr = { :a => 1, :b => 2, :c => 3 }
|
38
38
|
|
39
39
|
scrubbed = @governess.scrub(attr, :a, :c)
|
40
40
|
scrubbed.should be_kind_of(Kindergarten::ScrubbedHash)
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should rinse attributes" do
|
44
|
-
attr = { a
|
45
|
-
rinsed = @governess.rinse(attr, a
|
44
|
+
attr = { :a => 1, :b => "2a", :c => 3 }
|
45
|
+
rinsed = @governess.rinse(attr, :a => /(\d+)/, :b => /(\D+)/)
|
46
46
|
|
47
47
|
rinsed.should_not be_has_key(:c)
|
48
48
|
rinsed[:a].should eq "1"
|
@@ -50,16 +50,16 @@ describe Kindergarten::HeadGoverness do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should pass attributes" do
|
53
|
-
attr = { a
|
54
|
-
rinsed = @governess.rinse(attr, a
|
53
|
+
attr = { :a => "1", :b => "2a", :c => "3" }
|
54
|
+
rinsed = @governess.rinse(attr, :a => :pass, :c => :pass)
|
55
55
|
|
56
56
|
rinsed.should_not be_has_key(:b)
|
57
57
|
rinsed[:a].should eq "1"
|
58
58
|
rinsed[:c].should eq "3"
|
59
59
|
end
|
60
60
|
it "should return a RinsedHash after rinsing" do
|
61
|
-
attr = { a
|
62
|
-
rinsed = @governess.rinse(attr, a
|
61
|
+
attr = { :a => "1", :b => "2a", :c => "3" }
|
62
|
+
rinsed = @governess.rinse(attr, :a => /(\d+)/, :b => /(\d+)/)
|
63
63
|
|
64
64
|
rinsed.should be_kind_of(Kindergarten::RinsedHash)
|
65
65
|
end
|
@@ -2,29 +2,32 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Kindergarten::Perimeter do
|
4
4
|
describe :class do
|
5
|
-
it "should have a :
|
6
|
-
SpecPerimeter.should respond_to(:
|
7
|
-
SpecPerimeter.should respond_to(:
|
5
|
+
it "should have a :expose method" do
|
6
|
+
SpecPerimeter.should respond_to(:expose)
|
7
|
+
SpecPerimeter.should respond_to(:exposed_methods)
|
8
8
|
end
|
9
|
-
it "should return
|
10
|
-
SpecPerimeter.
|
9
|
+
it "should return exposed methods" do
|
10
|
+
SpecPerimeter.exposed_methods.should_not be_empty
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
it "should have a :govern method" do
|
14
14
|
SpecPerimeter.should respond_to(:govern)
|
15
15
|
SpecPerimeter.should respond_to(:govern_proc)
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
it "should return a govern proc" do
|
19
19
|
SpecPerimeter.govern_proc.should be_kind_of(Proc)
|
20
20
|
end
|
21
|
+
|
22
|
+
it "should return a governess"
|
23
|
+
it "should return a purpose"
|
21
24
|
end
|
22
25
|
|
23
26
|
describe :instance do
|
24
27
|
it "should have an initialize method with 2 arguments" do
|
25
28
|
SpecPerimeter.instance.method(:initialize).arity.should == 2
|
26
29
|
end
|
27
|
-
|
30
|
+
|
28
31
|
it "should have a :guard method" do
|
29
32
|
SpecPerimeter.instance.should respond_to(:guard)
|
30
33
|
end
|
@@ -45,66 +48,66 @@ describe Kindergarten::Perimeter do
|
|
45
48
|
SpecPerimeter.instance.should respond_to(:sandbox_methods)
|
46
49
|
end
|
47
50
|
end
|
48
|
-
|
51
|
+
|
49
52
|
describe :sandbox do
|
50
53
|
before(:each) do
|
51
54
|
@sandbox = Kindergarten.sandbox("child")
|
52
55
|
@sandbox.extend_perimeter(SpecPerimeter)
|
53
56
|
end
|
54
|
-
|
57
|
+
|
55
58
|
it "should have the SpecPerimeter" do
|
56
59
|
@sandbox.perimeter.collect(&:class).should include(SpecPerimeter)
|
57
60
|
end
|
58
|
-
|
61
|
+
|
59
62
|
it "should fill the governess" do
|
60
63
|
@sandbox.governess.should_not be_empty
|
61
64
|
end
|
62
65
|
|
63
66
|
it "should have the sandboxed method" do
|
64
|
-
@sandbox.sandboxed.should eq "child"
|
67
|
+
@sandbox.testing.sandboxed.should eq "child"
|
65
68
|
end
|
66
|
-
|
69
|
+
|
67
70
|
it "should have the guarded method" do
|
68
71
|
expect {
|
69
|
-
@sandbox.guarded
|
72
|
+
@sandbox.testing.guarded
|
70
73
|
}.to raise_error(Kindergarten::AccessDenied)
|
71
74
|
end
|
72
|
-
|
75
|
+
|
73
76
|
it "should not have the unboxed method" do
|
74
77
|
expect {
|
75
|
-
@sanbox.unboxed
|
78
|
+
@sanbox.testing.unboxed
|
76
79
|
}.to raise_error(NoMethodError)
|
77
80
|
end
|
78
|
-
|
81
|
+
|
79
82
|
it "should have the not_guarded method" do
|
80
|
-
@sandbox.not_guarded.should eq "OK"
|
83
|
+
@sandbox.testing.not_guarded.should eq "OK"
|
81
84
|
end
|
82
|
-
|
85
|
+
|
83
86
|
it "should have the unsafe method" do
|
84
|
-
expect {
|
85
|
-
@sandbox.unsafe
|
87
|
+
expect {
|
88
|
+
@sandbox.testing.unsafe
|
86
89
|
}.to raise_error(Kindergarten::Perimeter::Unguarded)
|
87
90
|
end
|
88
91
|
end
|
89
|
-
|
92
|
+
|
90
93
|
describe :unguarded do
|
91
94
|
before(:each) do
|
92
95
|
@sandbox = Kindergarten.sandbox("child")
|
93
96
|
@sandbox.extend_perimeter(SpecPerimeter)
|
94
97
|
end
|
95
|
-
|
98
|
+
|
96
99
|
it "should allow the unsafe method" do
|
97
|
-
expect {
|
100
|
+
expect {
|
98
101
|
@sandbox.unguarded do
|
99
|
-
@sandbox.unsafe
|
102
|
+
@sandbox.testing.unsafe
|
100
103
|
end
|
101
104
|
}.to_not raise_error(Kindergarten::Perimeter::Unguarded)
|
102
105
|
end
|
103
|
-
|
106
|
+
|
104
107
|
it "should allow the not_guarded method" do
|
105
|
-
expect {
|
108
|
+
expect {
|
106
109
|
@sandbox.unguarded do
|
107
|
-
@sandbox.not_guarded
|
110
|
+
@sandbox.testing.not_guarded
|
108
111
|
end
|
109
112
|
}.to_not raise_error(Kindergarten::Perimeter::Unguarded)
|
110
113
|
end
|
@@ -33,20 +33,54 @@ describe Kindergarten::Sandbox do
|
|
33
33
|
sandbox.perimeter.empty?
|
34
34
|
}
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
describe :HeadGoverness do
|
38
38
|
before(:each) do
|
39
39
|
@sandbox = Kindergarten::Sandbox.new(:child)
|
40
|
-
@sandbox.extend_perimeter(SpecPerimeter, PuppetPerimeter)
|
40
|
+
@sandbox.extend_perimeter(SpecPerimeter, PuppetPerimeter)
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should tell the outside what is allowed" do
|
44
44
|
@sandbox.should be_allowed(:view, "string")
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
it "should know the rules accross perimeters" do
|
48
|
-
puppet = @sandbox.grab_puppet
|
48
|
+
puppet = @sandbox.puppets.grab_puppet
|
49
49
|
@sandbox.should be_disallowed(:bbq, puppet)
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
describe :Loading do
|
54
|
+
before(:each) do
|
55
|
+
@sandbox = Kindergarten::Sandbox.new(:child)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should not load a module that has no sandboxed methods" do
|
59
|
+
expect {
|
60
|
+
@sandbox.load_module(MethodlessModule)
|
61
|
+
}.to raise_error(Kindergarten::Perimeter::NoExposedMethods, /MethodlessModule does not expose any methods/)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not load a module that has no purpose" do
|
65
|
+
expect {
|
66
|
+
@sandbox.load_module(PurposelessModule)
|
67
|
+
}.to raise_error(Kindergarten::Perimeter::NoPurpose, /PurposelessModule does not have a purpose/)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe :Purpose do
|
72
|
+
before(:each) do
|
73
|
+
@sandbox = Kindergarten::Sandbox.new(:kid)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should raise error for wrong purpose" do
|
77
|
+
expect {
|
78
|
+
@sandbox.empty.something
|
79
|
+
}.to raise_error(Kindergarten::Sandbox::NoPurposeError)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should return a hash of purposes" do
|
83
|
+
@sandbox.purpose.should be_kind_of(Hash)
|
84
|
+
end
|
85
|
+
end
|
52
86
|
end
|
@@ -10,7 +10,7 @@ class Migration < ActiveRecord::Migration
|
|
10
10
|
t.string :street
|
11
11
|
t.string :type
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
create_table :restaurants do |t|
|
15
15
|
t.string :name
|
16
16
|
t.text :description
|
@@ -30,7 +30,7 @@ end
|
|
30
30
|
|
31
31
|
class Restaurant < ActiveRecord::Base
|
32
32
|
include Kindergarten::ORM::Governess
|
33
|
-
|
33
|
+
|
34
34
|
force_rinsed
|
35
35
|
end
|
36
36
|
|
@@ -41,7 +41,7 @@ describe Kindergarten::ORM::ActiveRecord do
|
|
41
41
|
mig.suppress_messages do
|
42
42
|
mig.up
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
rescue => ex
|
46
46
|
unless ex.message =~ /already exists/
|
47
47
|
$stderr.puts "!!! #{ex.class}: #{ex.message}"
|
@@ -54,72 +54,72 @@ describe Kindergarten::ORM::ActiveRecord do
|
|
54
54
|
@sandbox = Kindergarten.sandbox(:child)
|
55
55
|
@sandbox.extend_perimeter(DrinkingPerimeter)
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
it "should create a bar" do
|
59
59
|
bar = nil
|
60
60
|
expect {
|
61
|
-
bar = @sandbox.create_bar( name
|
61
|
+
bar = @sandbox.get_drunk.create_bar( :name => "Foo", :decription => "A bar" )
|
62
62
|
}.to_not raise_error
|
63
|
-
|
63
|
+
|
64
64
|
bar.should be_kind_of(Bar)
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
it "should not create a bar w/o scrubbing" do
|
68
68
|
expect {
|
69
|
-
@sandbox.create_bar_wo( name
|
70
|
-
}.to raise_error(Kindergarten::ORM::Unscrubbed)
|
69
|
+
@sandbox.get_drunk.create_bar_wo( :name => "Foo", :decription => "A Bar" )
|
70
|
+
}.to raise_error(Kindergarten::ORM::Unscrubbed)
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
it "should protect the Joint" do
|
74
74
|
expect {
|
75
|
-
@sandbox.create_joint( name
|
76
|
-
}.to raise_error(Kindergarten::ORM::Unscrubbed)
|
75
|
+
@sandbox.get_drunk.create_joint( :name => "foo", :decription => "bar" )
|
76
|
+
}.to raise_error(Kindergarten::ORM::Unscrubbed)
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
it "should build a clean joint" do
|
80
80
|
expect {
|
81
|
-
@sandbox.build_joint(name
|
81
|
+
@sandbox.get_drunk.build_joint(:name => "clean")
|
82
82
|
}.to_not raise_error(Kindergarten::ORM::Unscrubbed)
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
it "should not build a dirty joint" do
|
86
86
|
expect {
|
87
|
-
@sandbox.build_dirty_joint
|
87
|
+
@sandbox.get_drunk.build_dirty_joint
|
88
88
|
}.to raise_error(Kindergarten::ORM::Unscrubbed)
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
it "should update a bar" do
|
92
|
-
bar = @sandbox.create_bar(name
|
92
|
+
bar = @sandbox.get_drunk.create_bar(:name => "Whiskey Inn")
|
93
93
|
expect {
|
94
|
-
@sandbox.update_bar(bar, name
|
94
|
+
@sandbox.get_drunk.update_bar(bar, :name => "Whiskey Out")
|
95
95
|
}.to_not raise_error(Kindergarten::ORM::Unscrubbed)
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
it "should not update a dirty bar" do
|
99
|
-
bar = @sandbox.create_bar(name
|
99
|
+
bar = @sandbox.get_drunk.create_bar(:name => "Whiskey Inn")
|
100
100
|
expect {
|
101
|
-
@sandbox.update_bar_dirty(bar, name
|
101
|
+
@sandbox.get_drunk.update_bar_dirty(bar, :name => "Whiskey Out")
|
102
102
|
}.to raise_error(Kindergarten::ORM::Unscrubbed)
|
103
|
-
end
|
103
|
+
end
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
describe :Dining do
|
107
107
|
before(:each) do
|
108
108
|
@sandbox = Kindergarten.sandbox(:child)
|
109
109
|
@sandbox.extend_perimeter(DiningPerimeter)
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
112
|
it "should not create a scrubbed restaurant" do
|
113
113
|
expect {
|
114
|
-
@sandbox.create_restaurant_scrubbed(name
|
114
|
+
@sandbox.eating.create_restaurant_scrubbed(:name => "China Wok")
|
115
115
|
}.to raise_error(Kindergarten::ORM::Unscrubbed)
|
116
116
|
end
|
117
|
-
|
117
|
+
|
118
118
|
it "should create a rinsed restaurant" do
|
119
119
|
expect {
|
120
|
-
@sandbox.create_restaurant(name
|
120
|
+
@sandbox.eating.create_restaurant(:name => "Lobster Inn")
|
121
121
|
}.to_not raise_error(Kindergarten::ORM::Unscrubbed)
|
122
122
|
end
|
123
123
|
end
|
124
|
-
|
125
|
-
end
|
124
|
+
|
125
|
+
end
|
data/spec/orm_helper.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
adapter = RUBY_PLATFORM == 'java' ? 'jdbc/mysql' : 'mysql2'
|
2
|
+
require adapter
|
3
|
+
|
2
4
|
require 'active_record'
|
3
5
|
require "kindergarten/orm/governess"
|
4
6
|
|
@@ -9,7 +11,8 @@ logger.formatter = proc { |severity, datetime, progname, msg|
|
|
9
11
|
|
10
12
|
ActiveRecord::Base.logger = logger
|
11
13
|
ActiveRecord::Base.establish_connection(
|
12
|
-
:adapter => '
|
13
|
-
:database =>
|
14
|
+
:adapter => adapter.gsub('/', ''),
|
15
|
+
:database => 'kindergarten_test',
|
16
|
+
:username => 'root',
|
17
|
+
:encoding => 'utf8'
|
14
18
|
)
|
15
|
-
|
@@ -1,14 +1,16 @@
|
|
1
1
|
class DiningPerimeter < Kindergarten::Perimeter
|
2
|
+
purpose :eating
|
3
|
+
|
2
4
|
# should raise Unscrubbed
|
3
5
|
def create_restaurant_scrubbed(args)
|
4
6
|
Restaurant.create(scrub(args, :name, :description))
|
5
7
|
end
|
6
|
-
|
8
|
+
|
7
9
|
# should work
|
8
10
|
def create_restaurant(args)
|
9
11
|
safe = rinse(args, :name => /([\w\s\-]+)/, :description => :pass)
|
10
12
|
Restaurant.create(safe)
|
11
13
|
end
|
12
|
-
|
14
|
+
|
13
15
|
sandbox :create_restaurant_scrubbed, :create_restaurant
|
14
|
-
end
|
16
|
+
end
|
@@ -1,39 +1,41 @@
|
|
1
1
|
class DrinkingPerimeter < Kindergarten::Perimeter
|
2
|
+
purpose :get_drunk
|
3
|
+
|
2
4
|
# supposed to work
|
3
5
|
def create_bar(args)
|
4
6
|
Bar.create(scrub(args, :name, :description))
|
5
7
|
end
|
6
|
-
|
8
|
+
|
7
9
|
# should raise Unscrubbed
|
8
10
|
def create_bar_wo(args)
|
9
11
|
Bar.create(args)
|
10
12
|
end
|
11
|
-
|
13
|
+
|
12
14
|
# should raise Unscrubbed
|
13
15
|
def create_joint(args)
|
14
16
|
Joint.create(args)
|
15
17
|
end
|
16
|
-
|
18
|
+
|
17
19
|
# should not raise Unscrubbed
|
18
20
|
def build_joint(args)
|
19
21
|
Joint.new(scrub(args, :name))
|
20
22
|
end
|
21
|
-
|
23
|
+
|
22
24
|
# should raise Unscrubbed
|
23
25
|
def build_dirty_joint
|
24
|
-
Joint.new(name
|
26
|
+
Joint.new(:name => "dirty")
|
25
27
|
end
|
26
|
-
|
28
|
+
|
27
29
|
# should not raise Unscrubbed
|
28
30
|
def update_bar(bar, args)
|
29
31
|
bar.update_attributes(scrub(args, :name, :city, :street))
|
30
32
|
end
|
31
|
-
|
33
|
+
|
32
34
|
# should raise
|
33
35
|
def update_bar_dirty(bar, args)
|
34
36
|
bar.update_attributes(args)
|
35
37
|
end
|
36
|
-
|
38
|
+
|
37
39
|
sandbox :create_bar, :create_bar_wo, :create_joint, :build_joint,
|
38
40
|
:build_dirty_joint, :update_bar, :update_bar_dirty
|
39
|
-
end
|
41
|
+
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
class PuppetPerimeter < Kindergarten::Perimeter
|
2
|
+
purpose :puppets
|
3
|
+
|
2
4
|
class Puppet
|
3
5
|
end
|
4
6
|
|
5
|
-
govern do
|
7
|
+
govern do
|
6
8
|
can [:play_with,:dress,:nappy_change], Puppet
|
7
9
|
cannot [:tear, :bbq], Puppet
|
8
10
|
end
|
@@ -16,4 +18,4 @@ class PuppetPerimeter < Kindergarten::Perimeter
|
|
16
18
|
end
|
17
19
|
|
18
20
|
sandbox :grab_puppet, :play_puppet
|
19
|
-
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kindergarten
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cancan
|
16
|
-
requirement: &
|
16
|
+
requirement: &24991920 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,21 +21,21 @@ dependencies:
|
|
21
21
|
version: 1.6.8
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *24991920
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: activesupport
|
27
|
-
requirement: &
|
27
|
+
requirement: &24991400 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
|
-
- -
|
30
|
+
- - ! '>'
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '3
|
32
|
+
version: '3'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *24991400
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake
|
38
|
-
requirement: &
|
38
|
+
requirement: &24991020 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,32 +43,43 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *24991020
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &24990460 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '2.
|
54
|
+
version: '2.11'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *24990460
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: activerecord
|
60
|
-
requirement: &
|
60
|
+
requirement: &24989940 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
|
-
- -
|
63
|
+
- - ! '>'
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '3'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *24989940
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mysql2
|
71
|
+
requirement: &24989560 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
64
75
|
- !ruby/object:Gem::Version
|
65
|
-
version: '
|
76
|
+
version: '0'
|
66
77
|
type: :development
|
67
78
|
prerelease: false
|
68
|
-
version_requirements: *
|
79
|
+
version_requirements: *24989560
|
69
80
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
71
|
-
requirement: &
|
81
|
+
name: jdbc-mysql
|
82
|
+
requirement: &24989100 !ruby/object:Gem::Requirement
|
72
83
|
none: false
|
73
84
|
requirements:
|
74
85
|
- - ! '>='
|
@@ -76,7 +87,7 @@ dependencies:
|
|
76
87
|
version: '0'
|
77
88
|
type: :development
|
78
89
|
prerelease: false
|
79
|
-
version_requirements: *
|
90
|
+
version_requirements: *24989100
|
80
91
|
description: A kindergarten with a perimeter, a governess and a sandbox
|
81
92
|
email:
|
82
93
|
- hartog@organisedminds.com
|
@@ -102,6 +113,7 @@ files:
|
|
102
113
|
- lib/kindergarten/orm/active_record.rb
|
103
114
|
- lib/kindergarten/orm/governess.rb
|
104
115
|
- lib/kindergarten/perimeter.rb
|
116
|
+
- lib/kindergarten/purpose.rb
|
105
117
|
- lib/kindergarten/sandbox.rb
|
106
118
|
- lib/kindergarten/version.rb
|
107
119
|
- spec/kindergarten/governess_spec.rb
|
@@ -116,7 +128,9 @@ files:
|
|
116
128
|
- spec/support/dining_perimeter.rb
|
117
129
|
- spec/support/drinking_perimeter.rb
|
118
130
|
- spec/support/log/.gitkeep
|
131
|
+
- spec/support/methodless_module.rb
|
119
132
|
- spec/support/puppet_perimeter.rb
|
133
|
+
- spec/support/purposeless_module.rb
|
120
134
|
- spec/support/spec_perimeter.rb
|
121
135
|
homepage: ''
|
122
136
|
licenses: []
|