mongoid-canhaz 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b14c99ec3f1ee2d7aea8e1ce4dc2be7ae8976eb3
4
+ data.tar.gz: 951457668fb45dd765fa435164a32e19f2cc13f3
5
+ SHA512:
6
+ metadata.gz: 3736d6b36da342b38b16df66c28a773d02767263b2cac73929ee4b0921f6b6f3c426d03334aee42761d1292b0e3a061bb9542729b56e5b4ad120d2076c349d51
7
+ data.tar.gz: 6ea2aef048c3763c81be5e44a951328365488f8aa5481b54eb332f1303e4eeb35944c3a1aa9630e57b7f5098c61a8f4f7cb9da1faa8008756cec1f2400f4ca6e
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+ *.swp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mongoid-canhaz.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ mongoid-canhaz (0.0.1)
5
+ mongoid (>= 2.2.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (3.2.12)
11
+ activesupport (= 3.2.12)
12
+ builder (~> 3.0.0)
13
+ activesupport (3.2.12)
14
+ i18n (~> 0.6)
15
+ multi_json (~> 1.0)
16
+ builder (3.0.4)
17
+ i18n (0.6.4)
18
+ mongoid (3.1.2)
19
+ activemodel (~> 3.2)
20
+ moped (~> 1.4.2)
21
+ origin (~> 1.0)
22
+ tzinfo (~> 0.3.22)
23
+ moped (1.4.3)
24
+ multi_json (1.7.2)
25
+ origin (1.0.11)
26
+ tzinfo (0.3.37)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ mongoid-canhaz!
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Intrepidd
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,81 @@
1
+ mongoid-canhaz
2
+ ====================
3
+
4
+ A mongoid port of the permissions gem for active record : rails-canhaz
5
+
6
+ This gem is a simple mongoid extention that allows any application using mongoid to manage permissions based roles.
7
+
8
+ ## Installation
9
+
10
+ Standard gem installation :
11
+
12
+ ```
13
+ gem install mongoid-canhaz
14
+ ```
15
+
16
+ Or in your Gemfile if you use bundler
17
+
18
+ ```ruby
19
+ gem 'mongoid-canhaz'
20
+ ```
21
+
22
+ ## How to use it ?
23
+
24
+ The mongoid-canhaz gem defines two static functions for mongoid documents which allow them to act as a subject or an object.
25
+
26
+ In order to use these functions, you need to include ``Canhaz::Mongoid::Document`` inside your class.
27
+
28
+ A subject has roles on objects.
29
+
30
+ Here is an example
31
+
32
+ ```ruby
33
+ class User
34
+ include Mongoid::Document
35
+ include Canhaz::Mongoid::Document
36
+
37
+ acts_as_canhaz_subject
38
+ end
39
+
40
+ class Article
41
+ include Mongoid::Document
42
+ include Canhaz::Mongoid::Document
43
+
44
+ acts_as_canhaz_object
45
+ end
46
+ ```
47
+
48
+ Now our models are marked as canhaz subjects and objects, we have access to some handy functions :
49
+
50
+
51
+ ```ruby
52
+ user = User.first
53
+ article = Article.first
54
+
55
+ user.can?(:read, article) # Can the user read this article? false for now
56
+
57
+ user.can!(:read, article) # Ok, so the user can read this article
58
+ user.can!(:edit, article) # He can edit it as well
59
+
60
+ user.can?(:read, article) # Will be true
61
+
62
+ user.objects_with_permission(Article, :read) # Will return all the articles w/ read permissions for this user
63
+
64
+ article.subjects_with_permission(User, :read) # Will return all the users hat are able to read this article
65
+
66
+ #You can also remove permissions
67
+
68
+ user.cannot!(:read, article)
69
+
70
+ # global permissions :
71
+
72
+ user.can?(:haz_cheezburgers) # false
73
+
74
+ user.can!(:haz_cheezburgers)
75
+
76
+ user.can?(:haz_cheezburgers) # true
77
+
78
+ ```
79
+
80
+ ## Changelog
81
+ * 1.0.0 : First release
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ require "mongoid-canhaz/version"
2
+ require "mongoid-canhaz/model_extentions"
3
+
4
+ module Canhaz
5
+ module Mongoid
6
+ module Document
7
+
8
+ def self.included(base)
9
+ base.send(:include, Canhaz::Mongoid::ModelExtensions)
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module Canhaz
2
+ module Mongoid
3
+ module Exceptions
4
+ class NotACanHazSubject < StandardError; end
5
+ class NotACanHazObject < StandardError; end
6
+ class NullPermission < StandardError ; end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ require 'mongoid-canhaz/permission'
2
+ require 'mongoid-canhaz/object_extensions'
3
+ require 'mongoid-canhaz/subject_extensions'
4
+
5
+ module Canhaz
6
+ module Mongoid
7
+
8
+ module ModelExtensions
9
+
10
+ def self.included(base)
11
+ base.send(:extend, ClassMethods)
12
+ end
13
+
14
+ def canhaz_object?
15
+ false
16
+ end
17
+
18
+ def canhaz_subject?
19
+ false
20
+ end
21
+
22
+ module ClassMethods
23
+
24
+ ##
25
+ # Marks the current model as a canhaz object for authorizations
26
+ #
27
+ def acts_as_canhaz_subject
28
+ include Canhaz::Mongoid::SubjectExtensions
29
+ has_many :permissions, :class_name => 'Canhaz::Mongoid::Permission', :inverse_of => 'csubject'
30
+ end
31
+
32
+ ##
33
+ # Marks the current model as a canhaz subject for authorizations
34
+ #
35
+ def acts_as_canhaz_object
36
+ include Canhaz::Mongoid::ObjectExtensions
37
+ class_eval do
38
+ has_many :permissions_subjects, :class_name => 'Canhaz::Mongoid::Permission', :inverse_of => 'cobject'
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ module Canhaz
2
+ module Mongoid
3
+ module ObjectExtensions
4
+
5
+ def canhaz_object?
6
+ true
7
+ end
8
+
9
+ # Gets the subjects that have the corresponding permission and type on this model
10
+ #
11
+ # @param type [Class] The type of the subjects we're looking for
12
+ # @param permission [String, Symbol] The permission
13
+ def subjects_with_permission(type, permission)
14
+ raise Exceptions::NotACanHazSubject unless type.respond_to?(:acts_as_canhaz_subject)
15
+ permissions = self.permissions_subjects.where(:type => self.class.to_s, :permission => permission.to_s)
16
+ type.in(:id => permissions.collect(&:csubject_id))
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ require 'mongoid'
2
+
3
+ module Canhaz
4
+ module Mongoid
5
+
6
+ class Permission
7
+ include ::Mongoid::Document
8
+
9
+ field :type, :type => String
10
+ field :csubject_id, :type => String
11
+ field :cobject_id, :type => String
12
+ field :permission, :type => String
13
+
14
+ validates :permission, :presence => true, :uniqueness => {:scope => [:type, :cobject_id, :csubject_id]}
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,98 @@
1
+ require 'mongoid-canhaz/exceptions'
2
+
3
+ module Canhaz
4
+ module Mongoid
5
+
6
+ module SubjectExtensions
7
+
8
+ def canhaz_subject?
9
+ true
10
+ end
11
+
12
+ # Creates a permission on a given object
13
+ #
14
+ # @param permission [String, Symbol] The identifier of the permission
15
+ # @param object [Object, nil] The model on which the permission is effective
16
+ # Can be nil if it is a global permission that does not target an object
17
+ # @return [Bool] True if the role was successfully created, false if it was already present
18
+ def can!(permission, object = nil)
19
+ assert_permission_not_nil(permission)
20
+ assert_canhaz_object(object)
21
+ object_type = object.nil? ? nil : object.class.to_s
22
+ object_id = object.nil? ? nil : object.id
23
+ perm = self.permissions.build(:permission => permission, :type => object_type, :cobject_id => object_id)
24
+ if perm.valid?
25
+ perm.save
26
+ return true
27
+ end
28
+ self.permissions.delete perm
29
+ perm.destroy
30
+ false
31
+ end
32
+
33
+ # Checks if the subject has a given permission on a given object
34
+ #
35
+ # @param permission [String, Symbol] The identifier of the permission
36
+ # @param object [Object, nil] The model we are testing the permission on
37
+ # Can be nil if it is a global permission that does not target an object
38
+ # @return [Bool] True if the user has the given permission, false otherwise
39
+ def can?(permission, object = nil)
40
+ assert_canhaz_object(object)
41
+ assert_permission_not_nil(permission)
42
+ find_canhaz_permission(object, permission).present?
43
+ end
44
+
45
+ # Checks if the subject does not have a given permission on a given object
46
+ # Acts as a proxy of !subject.can?(permission, object)
47
+ #
48
+ # @param permission [String, Symbol] The identifier of the permission
49
+ # @param object [Object] The model we are testing the permission on. Can be nil if it is a global permission that does not target an object
50
+ # @return [Bool] True if the user has not the given permission, false otherwise
51
+ def cannot?(permission, object = nil)
52
+ !self.can?(permission, object)
53
+ end
54
+
55
+ # Removes a permission on a given object
56
+ #
57
+ # @param permission [String, Symbol] The identifier of the permission
58
+ # @param object [Object, nil] The model on which the permission is effective. Can be nil if it is a global permission that does not target an object
59
+ # @return [Bool] True if the role was successfully removed, false if it did not exist
60
+ def cannot!(permission, object = nil)
61
+ assert_canhaz_object(object)
62
+ assert_permission_not_nil(permission)
63
+ row = find_canhaz_permission(object, permission)
64
+ return false unless row.present?
65
+ self.permissions.delete row
66
+ row.destroy and return true
67
+ end
68
+
69
+ # Gets All objects that match a given type and permission
70
+ #
71
+ # @param type [Class] The type of the objects
72
+ # @param permission [String, Symbol] The name of the permission
73
+ # @return The macthing objects in an array
74
+ def objects_with_permission(type, permission)
75
+ raise Exceptions::NotACanHazObject unless type.respond_to?(:acts_as_canhaz_object)
76
+ permissions = self.permissions.where(:permission => permission.to_s, :type => type.to_s)
77
+ type.in(:id => permissions.collect(&:cobject_id))
78
+ end
79
+
80
+ private
81
+
82
+ def assert_canhaz_object(object)
83
+ raise Exceptions::NotACanHazObject unless (object.nil? || (object.respond_to?('canhaz_object?') && object.canhaz_object?))
84
+ end
85
+
86
+ def assert_permission_not_nil(permission)
87
+ raise Exceptions::NullPermission unless permission.present?
88
+ end
89
+
90
+ def find_canhaz_permission(object, permission)
91
+ object_type = object.nil? ? nil : object.class.to_s
92
+ object_id = object.nil? ? nil : object.id.to_s
93
+ self.permissions.where(:permission => permission.to_s, :type => object_type, :cobject_id => object_id).to_a.first
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,5 @@
1
+ module Canhaz
2
+ module Mongoid
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mongoid-canhaz/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "mongoid-canhaz"
8
+ gem.version = Canhaz::Mongoid::VERSION
9
+ gem.authors = ["Intrepidd"]
10
+ gem.email = ["adrien@siami.fr"]
11
+ gem.description = "A simple mongoid extention that allows any application using mongoid to manage permissions based roles."
12
+ gem.summary = "A simple mongoid extention that allows any application using mongoid to manage permissions based roles."
13
+ gem.homepage = "https://github.com/Intrepidd/mongoid-canhaz/"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'mongoid', '>= 2.2.0'
21
+ end
@@ -0,0 +1,2 @@
1
+ ::Mongoid.connect_to('mongoid-canhaz')
2
+ ::Mongoid::Sessions.default.drop
@@ -0,0 +1,7 @@
1
+ class TestObject
2
+ include Mongoid::Document
3
+ include Canhaz::Mongoid::Document
4
+
5
+ acts_as_canhaz_object
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ class TestSubject
2
+ include Mongoid::Document
3
+ include Canhaz::Mongoid::Document
4
+
5
+ acts_as_canhaz_subject
6
+
7
+ end
@@ -0,0 +1,131 @@
1
+ require 'test/unit'
2
+ require 'mongoid'
3
+ require 'mongoid-canhaz'
4
+ require 'models/test_object'
5
+ require 'models/test_subject'
6
+ require 'init_connection'
7
+
8
+ class TestCanhaz < Test::Unit::TestCase
9
+ def test_methods
10
+ assert_equal true, TestObject.respond_to?(:acts_as_canhaz_object)
11
+ assert_equal true, TestSubject.respond_to?(:acts_as_canhaz_subject)
12
+
13
+ assert_equal true, TestObject.respond_to?(:acts_as_canhaz_subject)
14
+ assert_equal true, TestSubject.respond_to?(:acts_as_canhaz_object)
15
+
16
+ object = TestObject.new
17
+ subject = TestSubject.new
18
+
19
+ assert_equal true, object.canhaz_object?
20
+ assert_equal false, object.canhaz_subject?
21
+ assert_equal false, subject.canhaz_object?
22
+ assert_equal true, subject.canhaz_subject?
23
+ end
24
+
25
+
26
+ def test_can
27
+ object = TestObject.new
28
+ subject = TestSubject.new
29
+
30
+ object.save
31
+ subject.save
32
+
33
+ assert_equal 0, subject.permissions.size
34
+ assert_equal false, subject.can?(:foo, object)
35
+ assert_equal true, subject.cannot?(:foo, object)
36
+
37
+ assert_equal true, subject.can!(:foo, object)
38
+ assert_equal 1, subject.permissions.size
39
+ assert_equal 1, subject.reload.permissions.size
40
+ assert_equal true, subject.can?(:foo, object)
41
+ assert_equal false, subject.cannot?(:foo, object)
42
+
43
+ assert_equal false, subject.can!(:foo, object)
44
+ assert_equal 1, subject.permissions.size
45
+ assert_equal 1, subject.reload.permissions.size
46
+
47
+ assert_raise Canhaz::Mongoid::Exceptions::NotACanHazObject do
48
+ subject.can!(:foo, 1)
49
+ end
50
+
51
+ assert_equal true, subject.cannot!(:foo, object)
52
+ assert_equal 0, subject.permissions.size
53
+ assert_equal 0, subject.reload.permissions.size
54
+ assert_equal false, subject.can?(:foo, object)
55
+
56
+ assert_equal false, subject.can?(:bar)
57
+ assert_equal true, subject.cannot?(:bar)
58
+
59
+ assert_equal true, subject.can!(:bar)
60
+ assert_equal false, subject.cannot?(:bar)
61
+
62
+ assert_equal false, subject.can!(:bar)
63
+
64
+ assert_equal true, subject.cannot!(:bar)
65
+
66
+ assert_equal false, subject.can?(:bar)
67
+ assert_equal true, subject.cannot?(:bar)
68
+ end
69
+
70
+ def test_objects_with_permission
71
+ subject = TestSubject.new
72
+
73
+ o1 = TestObject.new
74
+ o2 = TestObject.new
75
+ o3 = TestObject.new
76
+
77
+ subject.save
78
+ o1.save
79
+ o2.save
80
+ o3.save
81
+
82
+ assert_equal [], subject.objects_with_permission(TestObject, :foo).to_a
83
+
84
+ subject.can!(:foo, o1)
85
+ assert_equal [o1], subject.objects_with_permission(TestObject, :foo).to_a
86
+ assert_equal [o1], subject.reload.objects_with_permission(TestObject, :foo).to_a
87
+
88
+ subject.can!(:bar, o2)
89
+ assert_equal [o1], subject.objects_with_permission(TestObject, :foo).to_a
90
+ assert_equal [o1], subject.reload.objects_with_permission(TestObject, :foo).to_a
91
+
92
+ subject.can!(:foo, o3)
93
+ assert_equal [o1, o3], subject.objects_with_permission(TestObject, :foo).to_a
94
+ assert_equal [o1, o3], subject.reload.objects_with_permission(TestObject, :foo).to_a
95
+
96
+ assert_raise Canhaz::Mongoid::Exceptions::NotACanHazObject do
97
+ subject.objects_with_permission(Fixnum, :foo)
98
+ end
99
+ end
100
+
101
+ def test_subjects_with_permission
102
+ object = TestObject.new
103
+ s1 = TestSubject.new
104
+ s2 = TestSubject.new
105
+ s3 = TestSubject.new
106
+
107
+ object.save
108
+ s1.save
109
+ s2.save
110
+ s3.save
111
+
112
+ assert_equal [], object.subjects_with_permission(TestSubject, :foo).to_a
113
+
114
+ assert_equal true, s1.can!(:foo, object)
115
+ assert_equal [s1], object.subjects_with_permission(TestSubject, :foo).to_a
116
+ assert_equal [s1], object.reload.subjects_with_permission(TestSubject, :foo).to_a
117
+
118
+ assert_equal true, s2.can!(:bar, object)
119
+ assert_equal [s1], object.subjects_with_permission(TestSubject, :foo).to_a
120
+ assert_equal [s1], object.reload.subjects_with_permission(TestSubject, :foo).to_a
121
+
122
+ assert_equal true, s3.can!(:foo, object)
123
+ assert_equal [s1, s3], object.subjects_with_permission(TestSubject, :foo).to_a
124
+ assert_equal [s1, s3], object.reload.subjects_with_permission(TestSubject, :foo).to_a
125
+
126
+ assert_raise Canhaz::Mongoid::Exceptions::NotACanHazSubject do
127
+ object.subjects_with_permission(Fixnum, :foo)
128
+ end
129
+ end
130
+
131
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid-canhaz
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Intrepidd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mongoid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.0
27
+ description: A simple mongoid extention that allows any application using mongoid
28
+ to manage permissions based roles.
29
+ email:
30
+ - adrien@siami.fr
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - .gitignore
36
+ - Gemfile
37
+ - Gemfile.lock
38
+ - LICENSE.txt
39
+ - README.md
40
+ - Rakefile
41
+ - lib/mongoid-canhaz.rb
42
+ - lib/mongoid-canhaz/exceptions.rb
43
+ - lib/mongoid-canhaz/model_extentions.rb
44
+ - lib/mongoid-canhaz/object_extensions.rb
45
+ - lib/mongoid-canhaz/permission.rb
46
+ - lib/mongoid-canhaz/subject_extensions.rb
47
+ - lib/mongoid-canhaz/version.rb
48
+ - mongoid-canhaz.gemspec
49
+ - test/init_connection.rb
50
+ - test/models/test_object.rb
51
+ - test/models/test_subject.rb
52
+ - test/test_canhaz.rb
53
+ homepage: https://github.com/Intrepidd/mongoid-canhaz/
54
+ licenses: []
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.0.3
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: A simple mongoid extention that allows any application using mongoid to manage
76
+ permissions based roles.
77
+ test_files:
78
+ - test/init_connection.rb
79
+ - test/models/test_object.rb
80
+ - test/models/test_subject.rb
81
+ - test/test_canhaz.rb