rails-canhaz 0.0.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ Gemfile.lock
3
+ *.sqlite3
4
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "activerecord", :require => "active_record"
4
+ gem "sqlite3"
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # Rails-Canhaz
2
+
3
+ This gem is a simple activerecord extention that allows any application using activerecord to manage permissions based roles.
4
+
5
+ ## Installation
6
+
7
+ Standard gem installation :
8
+
9
+ ```
10
+ gem install rails-canhaz
11
+ ```
12
+
13
+ Or in your Gemfile if you use bundler
14
+
15
+ ```ruby
16
+ gem 'rails-canhaz'
17
+ ```
18
+
19
+ You then need to create a single table in order to make this gem to work
20
+
21
+ Here is the schema of this table, if you're using ruby on rails, you should create a migration :
22
+
23
+ ```ruby
24
+ create_table :can_haz_permissions do |t|
25
+ t.integer :csubject_id
26
+ t.string :csubject_type
27
+
28
+ t.integer :cobject_id
29
+ t.string :cobject_type
30
+
31
+ t.string :permission_name
32
+ end
33
+
34
+ add_index :can_haz_permissions, :csubject_id, :name => 'subject_id_ix'
35
+ add_index :can_haz_permissions, :cobject_id, :name => 'object_id_ix'
36
+ ```
37
+
38
+ ## How to use it ?
39
+
40
+ The rails-canhaz gem defines two static functions for ActiveRecord models which allow them to act as a subject or an object.
41
+
42
+ A subject has roles on objects.
43
+
44
+ Here is an example
45
+
46
+ ```ruby
47
+ class User < ActiveRecord::Base
48
+ acts_as_canhaz_subject
49
+ end
50
+
51
+ class Article < ActiveRecord::Base
52
+ acts_as_canhaz_object
53
+ end
54
+ ```
55
+
56
+ Now our models are marked as canhaz subjects and objects, we have access to some handy functions :
57
+
58
+
59
+ ```ruby
60
+ user = User.find(42)
61
+ article = Article.find(1337)
62
+
63
+ user.can?(:read, article) # Can the user read this article? false for now
64
+
65
+ user.can(:read, article) # Ok, so the user can read this article
66
+
67
+ user.can?(:read, article) # Will be true
68
+
69
+ user.objects_with_permission(Article, :read) # Will return all the articles w/ read permissions for this user
70
+
71
+ artice.subjects_with_permission(User, :read) # Will return all the users hat are able to read this article
72
+ ```
73
+
74
+ More coming soon ...
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -0,0 +1,27 @@
1
+ require 'active_record'
2
+
3
+ class CanHazPermission < ActiveRecord::Base
4
+
5
+ validates :cobject_id, :uniqueness => {:scope => [:permission_name, :csubject_id]}
6
+
7
+ # Gets the permission row between two objects
8
+ #
9
+ # @param subject [ActiveRecord::Base] The subject
10
+ # @param object [ActiveRecord::Base] The object
11
+ # @param permission [String, Symbol] The permission identifier
12
+ # @return [CanHazPermission, nil] The corresponding permission if found or nil
13
+ def self.find_permission(subject, object, permission)
14
+ raise NotACanHazSubject unless subject.canhaz_subject?
15
+ raise NotACanHazObject unless object.canhaz_object?
16
+
17
+ results = CanHazPermission.where(
18
+ :csubject_id => subject.id,
19
+ :csubject_type => subject.class.to_s,
20
+ :cobject_id => object.id,
21
+ :cobject_type => object.class.to_s,
22
+ :permission_name => permission
23
+ )
24
+ results.first
25
+ end
26
+
27
+ end
@@ -0,0 +1,6 @@
1
+ module CanHaz
2
+ module Exceptions
3
+ class NotACanHazSubject < StandardError; end
4
+ class NotACanHazObject < StandardError; end
5
+ end
6
+ end
@@ -0,0 +1,21 @@
1
+ module CanHaz
2
+ module ModelExtensions
3
+ module All
4
+
5
+ # Returns if a model is registered as a canhaz subject
6
+ #
7
+ # @return [Bool] Whether or not the model is a canhaz subject
8
+ def canhaz_subject?
9
+ false
10
+ end
11
+
12
+ # Returns if a model is registered as a canhaz object
13
+ #
14
+ # @return [Bool] Whether or not the model is a canhaz object
15
+ def canhaz_object?
16
+ false
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ module CanHaz
2
+ module ModelExtensions
3
+ module Object
4
+
5
+ # Checks if the model is accessible by a given subject and a given permission
6
+ # This is a proxy to subject.can?(permission, subject)
7
+ #
8
+ # @param subject [ActiveRecord::Base] The subject we are testing
9
+ # @param permission [String, Symbol] The permission we want to test the subject on
10
+ # @return [Boolean] True if the subject has the permission on this object, false otherwise
11
+ def accessible_by?(subject, permission)
12
+ subject.can?(permission, self)
13
+ end
14
+
15
+ # Gets the subjects that have the corresponding permission and type on this model
16
+ #
17
+ # @param type [Class] The type of the subjects we're looking for
18
+ # @param permission [String, Symbol] The permission
19
+ def subjects_with_permission(type, permission)
20
+ results = CanHazPermission.where('cobject_id = ? AND cobject_type = ?', self.id, self.class.to_s).where('csubject_type = ?', type.to_s).where('permission_name = ?', permission)
21
+
22
+ ids = results.collect { |r| r.csubject_id }
23
+
24
+ type.where('id IN (?)', ids)
25
+ end
26
+
27
+ def canhaz_object?
28
+ true
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,71 @@
1
+ module CanHaz
2
+ module ModelExtensions
3
+ module Subject
4
+
5
+ # Creates a permission on a given object
6
+ #
7
+ # @param permission [String, Symbol] The identifier of the permission
8
+ # @param object [ActiveRecord::Base] The model on which the permission is effective
9
+ # @return [Bool] True if the role was successfully created, false if it was already present
10
+ def can(permission, object)
11
+ raise Exceptions::NotACanHazObject unless object.canhaz_object?
12
+ CanHazPermission.new({
13
+ :csubject_id => self.id,
14
+ :csubject_type => self.class.to_s,
15
+ :cobject_type => object.class.to_s,
16
+ :cobject_id => object.id,
17
+ :permission_name => permission
18
+ }).save
19
+ end
20
+
21
+ # Checks if the subject has a given permission on a given object
22
+ #
23
+ # @param permission [String, Symbol] The identifier of the permission
24
+ # @param object [ActiveRecord::Base] The model we are testing the permission on
25
+ # @return [Bool] True if the user has the given permission, false otherwise
26
+ def can?(permission, object)
27
+ raise Exceptions::NotACanHazObject unless object.canhaz_object?
28
+ CanHazPermission.find_permission(self, object, permission) != nil
29
+ end
30
+
31
+ # Removes a permission on a given object
32
+ #
33
+ # @param permission [String, Symbol] The identifier of the permission
34
+ # @param object [ActiveRecord::Base] The model on which the permission is effective
35
+ # @return [Bool] True if the role was successfully removed, false if it did not exist
36
+ def cannot(permission, object)
37
+ permission = CanHazPermission.find_permission(self, object, permission)
38
+ return false if permission.nil?
39
+ permission.destroy and return true
40
+ end
41
+
42
+ # Checks if the subject does not have a given permission on a given object
43
+ # Acts as a proxy of !subject.can?(permission, object)
44
+ #
45
+ # @param permission [String, Symbol] The identifier of the permission
46
+ # @param object [ActiveRecord::Base] The model we are testing the permission on
47
+ # @return [Bool] True if the user has not the given permission, false otherwise
48
+ def cannot?(permission, object)
49
+ !self.can?(permission, object)
50
+ end
51
+
52
+ # Gets All objects that match a given type and permission
53
+ #
54
+ # @param type [Class] The type of the objects
55
+ # @param permission [String, Symbol] The name of the permission
56
+ # @return The macthing objects in an array
57
+ def objects_with_permission(type, permission = nil)
58
+ results = CanHazPermission.where('csubject_id = ? AND csubject_type = ?', self.id, self.class.to_s).where('cobject_type = ?', type.to_s).where('permission_name = ?', permission)
59
+
60
+ ids = results.collect { |r| r.cobject_id }
61
+
62
+ type.where('id IN (?)', ids)
63
+ end
64
+
65
+ def canhaz_subject?
66
+ true
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,30 @@
1
+ require 'rails-canhaz/extensions_subject'
2
+ require 'rails-canhaz/extensions_object'
3
+ require 'rails-canhaz/extensions_all'
4
+
5
+ module CanHaz
6
+ module ModelExtensions
7
+ def self.included(base)
8
+ base.send(:extend, ClassMethods)
9
+ base.send(:include, CanHaz::ModelExtensions::All)
10
+ end
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ ##
16
+ # Marks the current model as a canhaz object for authorizations
17
+ #
18
+ def acts_as_canhaz_object
19
+ include CanHaz::ModelExtensions::Object
20
+ end
21
+
22
+ ##
23
+ # Marks the current model as a canhaz subject for authorizations
24
+ #
25
+ def acts_as_canhaz_subject
26
+ include CanHaz::ModelExtensions::Subject
27
+ end
28
+
29
+ end
30
+ end
data/lib/rails-canhaz.rb CHANGED
@@ -1,5 +1,7 @@
1
- class CanHaz
2
- def self.hi
3
- puts "Hello world, this is WIP :)"
4
- end
1
+ require 'rails-canhaz/exceptions'
2
+ require 'rails-canhaz/model_extensions'
3
+ require 'rails-canhaz/canhaz_permission'
4
+
5
+ if defined? ActiveRecord::Base
6
+ ActiveRecord::Base.send(:include, CanHaz::ModelExtensions)
5
7
  end
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'rails-canhaz'
3
+ s.version = '0.1.1'
4
+ s.date = '2012-04-16'
5
+ s.summary = "A simple gem for managing permissions between rails models"
6
+ s.description = "A simple gem for managing permissions between rails models"
7
+ s.authors = ["Adrien Siami (Intrepidd)"]
8
+ s.email = 'adrien@siami.fr'
9
+ s.files = `git ls-files`.split("\n")
10
+
11
+ s.homepage =
12
+ 'http://github.com/Intrepidd/rails-canhaz'
13
+ end
data/test/.gitkeep ADDED
File without changes
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'active_support'
4
+
5
+ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => 'test.sqlite3')
6
+
@@ -0,0 +1,5 @@
1
+ require 'active_record'
2
+ require 'rails-canhaz'
3
+
4
+ class FooModel < ActiveRecord::Base
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'active_record'
2
+ require 'rails-canhaz'
3
+
4
+ class ObjectModel < ActiveRecord::Base
5
+
6
+ acts_as_canhaz_object
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'active_record'
2
+ require 'rails-canhaz'
3
+
4
+ class SubjectModel < ActiveRecord::Base
5
+
6
+ acts_as_canhaz_subject
7
+
8
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,33 @@
1
+
2
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'object_models'")
3
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'subject_models'")
4
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'can_haz_permissions'")
5
+ ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS 'foo_models'")
6
+
7
+ ActiveRecord::Schema.define(:version => 0) do
8
+
9
+ create_table :object_models do |t|
10
+
11
+ end
12
+
13
+ create_table :subject_models do |t|
14
+
15
+ end
16
+
17
+ create_table :can_haz_permissions do |t|
18
+ t.integer :csubject_id
19
+ t.string :csubject_type
20
+
21
+ t.integer :cobject_id
22
+ t.string :cobject_type
23
+
24
+ t.string :permission_name
25
+ end
26
+
27
+ add_index :can_haz_permissions, :csubject_id, :name => 'subject_id_ix'
28
+ add_index :can_haz_permissions, :cobject_id, :name => 'object_id_ix'
29
+
30
+ create_table :foo_models do |t|
31
+ end
32
+
33
+ end
@@ -0,0 +1,155 @@
1
+ require 'init_tests'
2
+ require 'rails-canhaz'
3
+ require 'test/unit'
4
+ require 'models/object_model'
5
+ require 'models/subject_model'
6
+ require 'models/foo_model'
7
+
8
+ load 'schema.rb'
9
+
10
+ class CanHazTest < Test::Unit::TestCase
11
+
12
+ def test_methods
13
+ assert ActiveRecord::Base.respond_to? :acts_as_canhaz_object
14
+ assert ActiveRecord::Base.respond_to? :acts_as_canhaz_subject
15
+
16
+
17
+ foo = FooModel.new
18
+
19
+ assert foo.canhaz_object? == false
20
+ assert foo.canhaz_subject? == false
21
+
22
+ object = ObjectModel.new
23
+
24
+ assert object.canhaz_object?
25
+ assert object.canhaz_subject? == false
26
+
27
+ subject = SubjectModel.new
28
+
29
+ assert subject.canhaz_subject?
30
+ assert subject.canhaz_object? == false
31
+
32
+ end
33
+
34
+ def test_exceptions
35
+ foo = FooModel.new
36
+
37
+ subject = SubjectModel.new
38
+
39
+ object = ObjectModel.new
40
+
41
+ assert_raise CanHaz::Exceptions::NotACanHazObject do
42
+ subject.can(:whatever, foo)
43
+ end
44
+
45
+ assert_nothing_raised RuntimeError do
46
+ subject.can(:whatever, object)
47
+ end
48
+
49
+ assert_raise CanHaz::Exceptions::NotACanHazObject do
50
+ subject.can?(:whatever, foo)
51
+ end
52
+
53
+ assert_nothing_raised RuntimeError do
54
+ subject.can?(:whatever, object)
55
+ end
56
+
57
+ end
58
+
59
+ def test_can
60
+ subject = SubjectModel.new
61
+ subject.save
62
+
63
+ object = ObjectModel.new
64
+ object.save
65
+
66
+ assert subject.can?(:foo, object) == false
67
+ assert subject.can?(:bar, object) == false
68
+
69
+ assert object.accessible_by?(subject, :foo) == false
70
+ assert object.accessible_by?(subject, :bar) == false
71
+
72
+ assert subject.can(:foo, object)
73
+ assert subject.can(:bar, object)
74
+
75
+ assert subject.can(:foo, object) == false
76
+ assert subject.can(:bar, object) == false
77
+
78
+ assert subject.can?(:foo, object)
79
+ assert subject.can?(:bar, object)
80
+
81
+ assert object.accessible_by?(subject, :foo)
82
+ assert object.accessible_by?(subject, :bar)
83
+
84
+ assert subject.objects_with_permission(ObjectModel, :foo).count == 1
85
+ assert subject.objects_with_permission(ObjectModel, :foo).first == object
86
+
87
+ assert subject.objects_with_permission(ObjectModel, :bar).count == 1
88
+ assert subject.objects_with_permission(ObjectModel, :bar).first == object
89
+
90
+ assert subject.objects_with_permission(ObjectModel, :foobar).count == 0
91
+
92
+ end
93
+
94
+ def test_can_cannot
95
+ subject = SubjectModel.new
96
+ subject.save
97
+
98
+ object = ObjectModel.new
99
+ object.save
100
+
101
+ assert subject.can?(:foo, object) == false
102
+ assert subject.cannot(:foo, object) == false
103
+
104
+ subject.can(:foo, object)
105
+ subject.can(:bar, object)
106
+
107
+ assert subject.can?(:foo, object)
108
+ assert subject.can?(:bar, object)
109
+
110
+ assert subject.cannot(:foo, object) == true
111
+
112
+ assert subject.can?(:foo, object) == false
113
+ assert subject.can?(:bar, object) == true
114
+ end
115
+
116
+ def test_subjects_from_object
117
+ object = ObjectModel.new
118
+ object.save
119
+
120
+ s1 = SubjectModel.new
121
+ s2 = SubjectModel.new
122
+ s3 = SubjectModel.new
123
+
124
+ s1.save
125
+ s2.save
126
+ s3.save
127
+
128
+ s1.can(:foo, object)
129
+ s2.can(:bar, object)
130
+ s3.can(:foo, object)
131
+
132
+ foo = object.subjects_with_permission(SubjectModel, :foo)
133
+
134
+ assert foo.include?(s1) == true
135
+ assert foo.include?(s2) == false
136
+ assert foo.include?(s3) == true
137
+
138
+ s3.cannot(:foo, object)
139
+
140
+ foo = object.subjects_with_permission(SubjectModel, :foo)
141
+
142
+ assert foo.include?(s1) == true
143
+ assert foo.include?(s2) == false
144
+ assert foo.include?(s3) == false
145
+
146
+ bar = object.subjects_with_permission(SubjectModel, :bar)
147
+
148
+ assert bar.include?(s1) == false
149
+ assert bar.include?(s2) == true
150
+ assert bar.include?(s3) == false
151
+
152
+ end
153
+
154
+ end
155
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-canhaz
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-30 00:00:00.000000000 Z
12
+ date: 2012-04-16 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A simple gem for managing permissions between rails models
15
15
  email: adrien@siami.fr
@@ -17,8 +17,26 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
+ - .gitignore
21
+ - Gemfile
22
+ - README.md
23
+ - Rakefile
20
24
  - lib/rails-canhaz.rb
21
- homepage: http://rubygems.org/gems/rails-canhaz
25
+ - lib/rails-canhaz/canhaz_permission.rb
26
+ - lib/rails-canhaz/exceptions.rb
27
+ - lib/rails-canhaz/extensions_all.rb
28
+ - lib/rails-canhaz/extensions_object.rb
29
+ - lib/rails-canhaz/extensions_subject.rb
30
+ - lib/rails-canhaz/model_extensions.rb
31
+ - rails-canhaz.gemspec
32
+ - test/.gitkeep
33
+ - test/init_tests.rb
34
+ - test/models/foo_model.rb
35
+ - test/models/object_model.rb
36
+ - test/models/subject_model.rb
37
+ - test/schema.rb
38
+ - test/test_canhaz.rb
39
+ homepage: http://github.com/Intrepidd/rails-canhaz
22
40
  licenses: []
23
41
  post_install_message:
24
42
  rdoc_options: []
@@ -38,8 +56,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
38
56
  version: '0'
39
57
  requirements: []
40
58
  rubyforge_project:
41
- rubygems_version: 1.8.17
59
+ rubygems_version: 1.8.21
42
60
  signing_key:
43
61
  specification_version: 3
44
62
  summary: A simple gem for managing permissions between rails models
45
63
  test_files: []
64
+ has_rdoc: