permissable 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +52 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/init.rb +1 -0
- data/lib/permissable/member.rb +105 -0
- data/lib/permissable/permission.rb +23 -0
- data/lib/permissable/resource.rb +13 -0
- data/lib/permissable.rb +92 -0
- data/permissable.gemspec +58 -0
- data/test/helper.rb +10 -0
- data/test/test_permissable.rb +7 -0
- metadata +95 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Brent Kirby
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
= permissable
|
2
|
+
|
3
|
+
Permissable creates the ability to add a permissions system to "resources" based on a "member".
|
4
|
+
It allows you to define a member using the +permissable+ method:
|
5
|
+
|
6
|
+
class User < ActiveRecord::Base
|
7
|
+
permissable do |configure|
|
8
|
+
configure.permission_for :read, :posts, :categories
|
9
|
+
configure.permission_for [:read, :write, :moderate], :comments
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Permissable uses a single "permissions" table (and subsuquently a Permission model), with a polymorphic relationship
|
14
|
+
between both the member and the resource.
|
15
|
+
|
16
|
+
Important to know... This is my first attempt at a RubyGem. I'm using the gem itself for an application currently in development,
|
17
|
+
so you can be assured at least the basic functionality should work as it goes along. For the time being, I'm not writing any tests,
|
18
|
+
but there will be some later.
|
19
|
+
|
20
|
+
I decided to develop it because I couldn't find anything that achieved the same thing that didn't seem cumbersome or akward to configure.
|
21
|
+
|
22
|
+
This documention is incomplete... I'll add more later.
|
23
|
+
|
24
|
+
== Usage
|
25
|
+
|
26
|
+
class User < ActiveRecord::Base
|
27
|
+
permissable do |configure|
|
28
|
+
configure.permission_for :read, :posts, :categories
|
29
|
+
configure.permission_for [:read, :write, :moderate], :comments
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
The permissable method accepts a block containing permission declarations.
|
34
|
+
Each call to permission_for accepts two attributes.
|
35
|
+
|
36
|
+
* method: The permission you want to assign (read, write, moderate, etc)
|
37
|
+
* resources: A list of resources to assign those permissions to
|
38
|
+
|
39
|
+
|
40
|
+
== Note on Patches/Pull Requests
|
41
|
+
|
42
|
+
* Fork the project.
|
43
|
+
* Make your feature addition or bug fix.
|
44
|
+
* Add tests for it. This is important so I don't break it in a
|
45
|
+
future version unintentionally.
|
46
|
+
* Commit, do not mess with rakefile, version, or history.
|
47
|
+
(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)
|
48
|
+
* Send me a pull request. Bonus points for topic branches.
|
49
|
+
|
50
|
+
== Copyright
|
51
|
+
|
52
|
+
Copyright (c) 2010 kurb media, llc. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "permissable"
|
8
|
+
gem.summary = %Q{Basic member/resource permission system for ActiveRecord objects.}
|
9
|
+
gem.description = %Q{Permissable lets you set a number of 'permissions' to your database models. By assigning 'members' to 'resources' (models) you can specify various permission states.}
|
10
|
+
gem.email = "brent@kurbmedia.com"
|
11
|
+
gem.homepage = "http://github.com/kurbmedia/permissable"
|
12
|
+
gem.authors = ["Brent Kirby"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
task :test => :check_dependencies
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "permissable #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'permissable'
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Permissable
|
2
|
+
|
3
|
+
module Member
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
|
7
|
+
base.send :include, InstanceMethods
|
8
|
+
|
9
|
+
if base.permissable_by_association
|
10
|
+
base.send :include, AssociatedMethods
|
11
|
+
# Add a has many to our association so it can find permissions.
|
12
|
+
base.permissable_by_association.to_s.classify.constantize.class_eval do
|
13
|
+
has_many :permissions, :as => :member, :conditions => { :member_type => "#{self.to_s}" }
|
14
|
+
end
|
15
|
+
else
|
16
|
+
base.send :include, MemberMethods
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# This module includes methods that should exist on ALL members.
|
21
|
+
module InstanceMethods
|
22
|
+
|
23
|
+
# Can this member perform the requested action?
|
24
|
+
def can?(method, resource)
|
25
|
+
method = method.to_s
|
26
|
+
permissions.for_resource(resource).with_permission_to(method).exists?
|
27
|
+
end
|
28
|
+
|
29
|
+
# Set a permission
|
30
|
+
def can!(method, resource)
|
31
|
+
method = method.to_s.downcase
|
32
|
+
klassname = permissable_by_association ? permissable_by_association.to_s.classify : self.class.to_s
|
33
|
+
|
34
|
+
throw Permissable::ResourceNotPermissable unless resource.respond_to? :permissable_methods
|
35
|
+
throw Permissable::PermissionNotDefined unless resource.permissable_methods.include?(method)
|
36
|
+
|
37
|
+
members.each do |m|
|
38
|
+
next if resource.permissions.for_member_and_resource(m,resource).exists?
|
39
|
+
new_permission = Permission.new()
|
40
|
+
new_permission.member = m
|
41
|
+
new_permission.resource = resource
|
42
|
+
new_permission.permission_type = method
|
43
|
+
new_permission.save
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
def permissions_for(resource)
|
49
|
+
if resource.is_a?(Class)
|
50
|
+
permissions_scope[resource.to_s]
|
51
|
+
else
|
52
|
+
permissions.for_resource(resource).all.collect{ |p| p.permission_type.to_sym }.uniq
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def permissions_for?(resource)
|
57
|
+
!permissions_for(resource).empty?
|
58
|
+
end
|
59
|
+
|
60
|
+
def permissions_for!(resources, *perms)
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def get_const(resource)
|
67
|
+
resource.class.to_s.classify.constantize
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
# This module gets included on member classes that are permissable directly.
|
73
|
+
module MemberMethods
|
74
|
+
alias_attribute :member_id, :id
|
75
|
+
def members; [self]; end
|
76
|
+
end
|
77
|
+
|
78
|
+
# This module gets included on member classes that are permissable with an association.
|
79
|
+
module AssociatedMethods
|
80
|
+
|
81
|
+
attr_reader :permissions
|
82
|
+
attr_reader :member_id
|
83
|
+
|
84
|
+
def permissions
|
85
|
+
return @permissions unless @permissions.nil?
|
86
|
+
@permissions = Permission.where(:member_id => member_id, :member_type => association.to_s)
|
87
|
+
end
|
88
|
+
|
89
|
+
def association
|
90
|
+
permissable_by_association.to_s.classify.constantize
|
91
|
+
end
|
92
|
+
|
93
|
+
def member_id
|
94
|
+
@member_id || association.all.collect{ |a| a.attributes['id'] }
|
95
|
+
end
|
96
|
+
|
97
|
+
def members
|
98
|
+
association.all
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Permission < ActiveRecord::Base
|
2
|
+
belongs_to :member, :polymorphic => true
|
3
|
+
belongs_to :resource, :polymorphic => true
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def for_member(member)
|
7
|
+
where(:member_id => member.id, :member_type => member.class.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def for_resource(resource)
|
11
|
+
where(:resource_id => resource.id, :resource_type => resource.class.to_s)
|
12
|
+
end
|
13
|
+
|
14
|
+
def for_member_and_resource(member, resource)
|
15
|
+
for_member(member).for_resource(resource)
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_permission_to(perm)
|
19
|
+
where(:permission_type => perm.to_s)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/permissable.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# Author: Brent Kirby
|
2
|
+
# Copyright:: Copyright (c) 2010 kurb media, llc.
|
3
|
+
# License:: MIT License (http://www.opensource.org/licenses/mit-license.php)
|
4
|
+
#
|
5
|
+
# Permissable creates the ability to add a permissions system to "resources" based on a "member".
|
6
|
+
# It allows you to define a member using the +permissable+ method:
|
7
|
+
#
|
8
|
+
# class User < ActiveRecord::Base
|
9
|
+
# permissable do |configure|
|
10
|
+
# configure.permission_for :read, :posts, :categories
|
11
|
+
# configure.permission_for [:read, :write, :moderate], :comments
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# Permissable uses a single "permissions" table (and subsuquently a Permission model), with a polymorphic relationship
|
16
|
+
# between both the member and the resource.
|
17
|
+
|
18
|
+
require 'permissable/member'
|
19
|
+
require 'permissable/permission'
|
20
|
+
require 'permissable/resource'
|
21
|
+
|
22
|
+
module Permissable
|
23
|
+
|
24
|
+
class << self
|
25
|
+
|
26
|
+
def included(base)
|
27
|
+
base.extend ClassMethods
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
class PermissableError < StandardError
|
33
|
+
end
|
34
|
+
|
35
|
+
class PermissionNotDefined < PermissableError
|
36
|
+
end
|
37
|
+
|
38
|
+
class ResourceNotPermissable < PermissableError
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
|
43
|
+
# +permissable+ gives the class its called on the ability to effect various permission states on the resources
|
44
|
+
# it specifies. It accepts an options hash and a block. The following options are supported:
|
45
|
+
#
|
46
|
+
# * with: This is an association of the primary member class. This allows you to use an association to determine
|
47
|
+
# which permissions are available. One example of this would be to assign permission to Roles of a User class.
|
48
|
+
# In this case, when doing lookups, it will use the permissions assigned to each Role the user belongs to.
|
49
|
+
# The with option accepts the association in the same manner as you would define it in active record.
|
50
|
+
# ie: has_many roles would be: :with => :roles. belongs_to role would be :with => :role
|
51
|
+
def permissable(options = {})
|
52
|
+
|
53
|
+
write_inheritable_attribute :permissable_by_association, (options[:with] || false)
|
54
|
+
class_inheritable_reader :permissable_by_association
|
55
|
+
|
56
|
+
# The class that called permissable becomes a member.
|
57
|
+
include Permissable::Member
|
58
|
+
has_many(:permissions, :as => :member, :conditions => { :member_type => "#{self.to_s}" }) unless permissable_by_association
|
59
|
+
|
60
|
+
yield self
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# +permission_for+ is called via the permissable block
|
65
|
+
def permission_for(methods, *resources)
|
66
|
+
|
67
|
+
methods = [methods] unless methods.is_a?(Array)
|
68
|
+
|
69
|
+
resources.each do |resource|
|
70
|
+
|
71
|
+
klass = resource.to_s.classify
|
72
|
+
klass.constantize.class_eval do
|
73
|
+
|
74
|
+
write_inheritable_attribute :permissable_methods, methods
|
75
|
+
class_inheritable_reader :permissable_methods
|
76
|
+
has_many(:permissions, :as => :resource, :conditions => { :resource_type => "#{self.to_s}" })
|
77
|
+
|
78
|
+
include Permissable::Resource
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
ActiveSupport.on_load :active_record do
|
91
|
+
ActiveRecord::Base.send :include, Permissable
|
92
|
+
end
|
data/permissable.gemspec
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{permissable}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Brent Kirby"]
|
12
|
+
s.date = %q{2010-07-25}
|
13
|
+
s.description = %q{Permissable lets you set a number of 'permissions' to your database models. By assigning 'members' to 'resources' (models) you can specify various permission states.}
|
14
|
+
s.email = %q{brent@kurbmedia.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"init.rb",
|
27
|
+
"lib/permissable.rb",
|
28
|
+
"lib/permissable/member.rb",
|
29
|
+
"lib/permissable/permission.rb",
|
30
|
+
"lib/permissable/resource.rb",
|
31
|
+
"permissable.gemspec",
|
32
|
+
"test/helper.rb",
|
33
|
+
"test/test_permissable.rb"
|
34
|
+
]
|
35
|
+
s.homepage = %q{http://github.com/kurbmedia/permissable}
|
36
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
37
|
+
s.require_paths = ["lib"]
|
38
|
+
s.rubygems_version = %q{1.3.7}
|
39
|
+
s.summary = %q{Basic member/resource permission system for ActiveRecord objects.}
|
40
|
+
s.test_files = [
|
41
|
+
"test/helper.rb",
|
42
|
+
"test/test_permissable.rb"
|
43
|
+
]
|
44
|
+
|
45
|
+
if s.respond_to? :specification_version then
|
46
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
47
|
+
s.specification_version = 3
|
48
|
+
|
49
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
50
|
+
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
53
|
+
end
|
54
|
+
else
|
55
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
data/test/helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: permissable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Brent Kirby
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-25 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: thoughtbot-shoulda
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Permissable lets you set a number of 'permissions' to your database models. By assigning 'members' to 'resources' (models) you can specify various permission states.
|
36
|
+
email: brent@kurbmedia.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.rdoc
|
44
|
+
files:
|
45
|
+
- .document
|
46
|
+
- .gitignore
|
47
|
+
- LICENSE
|
48
|
+
- README.rdoc
|
49
|
+
- Rakefile
|
50
|
+
- VERSION
|
51
|
+
- init.rb
|
52
|
+
- lib/permissable.rb
|
53
|
+
- lib/permissable/member.rb
|
54
|
+
- lib/permissable/permission.rb
|
55
|
+
- lib/permissable/resource.rb
|
56
|
+
- permissable.gemspec
|
57
|
+
- test/helper.rb
|
58
|
+
- test/test_permissable.rb
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://github.com/kurbmedia/permissable
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options:
|
65
|
+
- --charset=UTF-8
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 3
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
version: "0"
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.3.7
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: Basic member/resource permission system for ActiveRecord objects.
|
93
|
+
test_files:
|
94
|
+
- test/helper.rb
|
95
|
+
- test/test_permissable.rb
|