checkin 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +19 -0
- data/LICENSE.txt +20 -0
- data/README.md +188 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/checkin.gemspec +57 -0
- data/lib/checkin/access_denied.rb +46 -0
- data/lib/checkin/dsl/permissions.rb +167 -0
- data/lib/checkin/dsl/roles.rb +149 -0
- data/lib/checkin/filters.rb +78 -0
- data/lib/checkin/role.rb +26 -0
- data/lib/checkin/rule.rb +104 -0
- data/lib/checkin/subject.rb +137 -0
- data/lib/checkin.rb +32 -0
- data/test/helper.rb +18 -0
- data/test/test_checkin.rb +7 -0
- metadata +84 -0
data/.document
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
git (1.2.5)
|
5
|
+
jeweler (1.8.3)
|
6
|
+
bundler (~> 1.0)
|
7
|
+
git (>= 1.2.5)
|
8
|
+
rake
|
9
|
+
rdoc
|
10
|
+
json (1.7.1)
|
11
|
+
rake (0.9.2.2)
|
12
|
+
rdoc (3.12)
|
13
|
+
json (~> 1.4)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
jeweler (~> 1.8.3)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 mcasimir
|
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.md
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
# Checkin
|
2
|
+
|
3
|
+
**Checkin** is an authorization gem for Ruby on Rails
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Put this in your Gemfile
|
8
|
+
|
9
|
+
gem 'checkin'
|
10
|
+
|
11
|
+
and update your bundle
|
12
|
+
|
13
|
+
bundle install
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
Create a **subject class** in your load path
|
18
|
+
|
19
|
+
_ex._
|
20
|
+
|
21
|
+
``` rb
|
22
|
+
class UserSubject < Checkin::Subject
|
23
|
+
|
24
|
+
role :guest, :alias => :anonymous do
|
25
|
+
!subject_model
|
26
|
+
end
|
27
|
+
|
28
|
+
role :logged_in, :alias => [:connected] do
|
29
|
+
!!subject_model
|
30
|
+
end
|
31
|
+
|
32
|
+
role :owner, :require => [:logged_in, :author], :method => :own do |object|
|
33
|
+
object && object.respond_to?(:author) && ( subject_model == object.author )
|
34
|
+
end
|
35
|
+
|
36
|
+
role :author, :require => :logged_in do
|
37
|
+
subject_model.has_role?(:contributor) || subject_model.has_role?(:author)
|
38
|
+
end
|
39
|
+
|
40
|
+
role :editor, :require => :logged_in do
|
41
|
+
subject_model.has_role?(:editor)
|
42
|
+
end
|
43
|
+
|
44
|
+
role :administrator, :require => :logged_in, :alias => :admin do
|
45
|
+
subject_model.has_role?(:administrator)
|
46
|
+
end
|
47
|
+
|
48
|
+
role :mantainer, :require => :logged_in do
|
49
|
+
subject_model.has_role?(:mantainer)
|
50
|
+
end
|
51
|
+
|
52
|
+
role :staff, :require => :logged_in do
|
53
|
+
subject_model.has_role?(:administrator) ||
|
54
|
+
subject_model.has_role?(:mantainer) ||
|
55
|
+
subject_model.has_role?(:editor) ||
|
56
|
+
subject_model.has_role?(:author) ||
|
57
|
+
subject_model.has_role?(:contributor) ||
|
58
|
+
subject_model.has_role?(:photographer)
|
59
|
+
end
|
60
|
+
|
61
|
+
role :tester, :require => :logged_in do
|
62
|
+
subject_model.has_role?(:tester)
|
63
|
+
end
|
64
|
+
|
65
|
+
role :nexta_supervisor, :require => :logged_in do
|
66
|
+
subject_model.has_role?(:nexta)
|
67
|
+
end
|
68
|
+
|
69
|
+
role :self, :require => :logged_in do |object|
|
70
|
+
object && object.is_a?(User) && subject_model == object
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Permissions
|
75
|
+
#
|
76
|
+
|
77
|
+
scope :site do
|
78
|
+
permissions :for => [:messages, :replies] do
|
79
|
+
allow :logged_in
|
80
|
+
allow :guests, :to => [:show, :index]
|
81
|
+
deny :guests
|
82
|
+
end
|
83
|
+
permissions :for => :network do
|
84
|
+
allow [:administrators, :nexta_supervisors], :to => [:see]
|
85
|
+
deny
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Admin
|
90
|
+
scope :admin do
|
91
|
+
permissions do
|
92
|
+
allow :administrators, :mantainers
|
93
|
+
deny
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
scope :api do
|
98
|
+
allow :staff
|
99
|
+
deny
|
100
|
+
end
|
101
|
+
|
102
|
+
# Mantainer
|
103
|
+
scope :mantainer do
|
104
|
+
permissions do
|
105
|
+
allow :mantainers
|
106
|
+
deny
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Staff
|
111
|
+
scope :staff do
|
112
|
+
permissions do
|
113
|
+
allow :administrators, :mantainers
|
114
|
+
allow :editors, :to => [:edit, :update]
|
115
|
+
allow :authors, :to => [:new, :create]
|
116
|
+
allow :owners, :to => [:edit, :update]
|
117
|
+
deny
|
118
|
+
end
|
119
|
+
|
120
|
+
permissions :for => :guides do
|
121
|
+
allow :administrators, :mantainers
|
122
|
+
allow :logged_in, :to => [:index, :show]
|
123
|
+
deny
|
124
|
+
end
|
125
|
+
|
126
|
+
permissions :for => :drafts do
|
127
|
+
allow :authors, :to => :submit
|
128
|
+
end
|
129
|
+
|
130
|
+
permissions_to_set :published do
|
131
|
+
allow :editors, :administrators, :mantainers
|
132
|
+
deny
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
Use in controller
|
140
|
+
|
141
|
+
_ex._
|
142
|
+
|
143
|
+
``` rb
|
144
|
+
class ApplicationController < ActionController::Base
|
145
|
+
rescue_from Checkin::AccessDenied, :with => :rescue_access_denied
|
146
|
+
|
147
|
+
protect_from_forgery
|
148
|
+
checkin(:scope => :admin)
|
149
|
+
|
150
|
+
protected
|
151
|
+
|
152
|
+
def rescue_access_denied
|
153
|
+
if subject.guest?
|
154
|
+
redirect_to new_user_session_path, :notice => "Accedi per completare l'operazione"
|
155
|
+
else
|
156
|
+
render :text => "Not Authorized", :status => 403
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
```
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
---
|
167
|
+
|
168
|
+
Copyright (c) 2012 mcasimir
|
169
|
+
|
170
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
171
|
+
a copy of this software and associated documentation files (the
|
172
|
+
"Software"), to deal in the Software without restriction, including
|
173
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
174
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
175
|
+
permit persons to whom the Software is furnished to do so, subject to
|
176
|
+
the following conditions:
|
177
|
+
|
178
|
+
The above copyright notice and this permission notice shall be
|
179
|
+
included in all copies or substantial portions of the Software.
|
180
|
+
|
181
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
182
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
183
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
184
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
185
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
186
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
187
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
188
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "checkin"
|
18
|
+
gem.homepage = "http://github.com/mcasimir/checkin"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Checkin is an authorization gem for Ruby on Rails}
|
21
|
+
gem.description = %Q{Checkin is an authorization gem for Ruby on Rails}
|
22
|
+
gem.email = "maurizio.cas@gmail.com"
|
23
|
+
gem.authors = ["mcasimir"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.3
|
data/checkin.gemspec
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "checkin"
|
8
|
+
s.version = "0.4.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["mcasimir"]
|
12
|
+
s.date = "2012-05-07"
|
13
|
+
s.description = "Checkin is an authorization gem for Ruby on Rails"
|
14
|
+
s.email = "maurizio.cas@gmail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.md",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION",
|
27
|
+
"checkin.gemspec",
|
28
|
+
"lib/checkin.rb",
|
29
|
+
"lib/checkin/access_denied.rb",
|
30
|
+
"lib/checkin/dsl/permissions.rb",
|
31
|
+
"lib/checkin/dsl/roles.rb",
|
32
|
+
"lib/checkin/filters.rb",
|
33
|
+
"lib/checkin/role.rb",
|
34
|
+
"lib/checkin/rule.rb",
|
35
|
+
"lib/checkin/subject.rb",
|
36
|
+
"test/helper.rb",
|
37
|
+
"test/test_checkin.rb"
|
38
|
+
]
|
39
|
+
s.homepage = "http://github.com/mcasimir/checkin"
|
40
|
+
s.licenses = ["MIT"]
|
41
|
+
s.require_paths = ["lib"]
|
42
|
+
s.rubygems_version = "1.8.24"
|
43
|
+
s.summary = "Checkin is an authorization gem for Ruby on Rails"
|
44
|
+
|
45
|
+
if s.respond_to? :specification_version then
|
46
|
+
s.specification_version = 3
|
47
|
+
|
48
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
52
|
+
end
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Author:: Maurizio Casimirri (mailto:maurizio.cas@gmail.com)
|
2
|
+
# Copyright:: Copyright (c) 2012 Maurizio Casimirri
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
module Checkin
|
24
|
+
class AccessDenied < StandardError
|
25
|
+
attr_reader :subject, :action, :resource, :object
|
26
|
+
|
27
|
+
def initialize(subject, action, object_or_resource, options = {})
|
28
|
+
|
29
|
+
@message = options[:message]
|
30
|
+
@subject = subject
|
31
|
+
@action = action
|
32
|
+
@object = ( object_or_resource.is_a?(Symbol) || object_or_resource.is_a?(String)) ? nil : object_or_resource
|
33
|
+
@resource = object ? object.class.name.demodulize.underscore.to_sym : "#{object_or_resource}".singularize.to_sym
|
34
|
+
|
35
|
+
@default_message = I18n.t(:"unauthorized.default", :default => "You are not authorized to access this page.")
|
36
|
+
end
|
37
|
+
|
38
|
+
def scope
|
39
|
+
@subject.scope if @subject
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
@message || @default_message
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# Author:: Maurizio Casimirri (mailto:maurizio.cas@gmail.com)
|
2
|
+
# Copyright:: Copyright (c) 2012 Maurizio Casimirri
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'checkin/rule'
|
24
|
+
|
25
|
+
#
|
26
|
+
# Permissions DSL
|
27
|
+
#
|
28
|
+
|
29
|
+
module Checkin
|
30
|
+
module Dsl
|
31
|
+
module Permissions
|
32
|
+
extend ActiveSupport::Concern
|
33
|
+
|
34
|
+
included do
|
35
|
+
attr_writer :explain
|
36
|
+
end
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
|
40
|
+
def rules
|
41
|
+
@rules ||= []
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_rule_block(rules)
|
45
|
+
@rules ||= []
|
46
|
+
@rules = rules + @rules
|
47
|
+
end
|
48
|
+
|
49
|
+
def attribute_rules
|
50
|
+
@attribute_rules ||= []
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_attribute_rules_block(rules)
|
54
|
+
@attribute_rules ||= []
|
55
|
+
@attribute_rules = rules + @attribute_rules
|
56
|
+
end
|
57
|
+
|
58
|
+
def scope(scope, &block)
|
59
|
+
_current_options[:scope] = scope
|
60
|
+
yield
|
61
|
+
_current_options.delete(:scope)
|
62
|
+
end
|
63
|
+
|
64
|
+
def permissions(*args)
|
65
|
+
_current_options[:mode] = :cascade
|
66
|
+
opts = args.extract_options!
|
67
|
+
_current_options[:resources] = [opts[:for]].flatten.compact.uniq.map {|r| "#{r}".singularize.to_sym}
|
68
|
+
yield
|
69
|
+
add_rule_block(_current_rule_block)
|
70
|
+
_reset_current_options
|
71
|
+
_reset_current_rule_block
|
72
|
+
end
|
73
|
+
|
74
|
+
def permissions_to_set(*args)
|
75
|
+
_current_options[:mode] = :attributes
|
76
|
+
opts = args.extract_options!
|
77
|
+
resources_options = opts[:on]
|
78
|
+
_current_options[:resources] = [resources_options].flatten.compact.uniq.map {|r| "#{r}".singularize.to_sym}
|
79
|
+
_current_options[:attributes] = args.flatten
|
80
|
+
yield
|
81
|
+
add_attribute_rules_block(_current_attributes_block)
|
82
|
+
_reset_current_options
|
83
|
+
_reset_current_attributes_block
|
84
|
+
end
|
85
|
+
|
86
|
+
def allow(*args)
|
87
|
+
if _current_options[:mode] == :cascade
|
88
|
+
_add_rule_to_current_rule_block(:allow, *args)
|
89
|
+
elsif _current_options[:mode] == :attributes
|
90
|
+
_add_rule_to_current_attributes_block(:allow, *args)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def deny(*args)
|
95
|
+
if _current_options[:mode] == :cascade
|
96
|
+
_add_rule_to_current_rule_block(:deny, *args)
|
97
|
+
elsif _current_options[:mode] == :attributes
|
98
|
+
_add_rule_to_current_attributes_block(:deny, *args)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def _current_options
|
103
|
+
@_current_options ||= ::ActiveSupport::HashWithIndifferentAccess.new
|
104
|
+
end
|
105
|
+
|
106
|
+
def _reset_current_options
|
107
|
+
scope = _current_options[:scope]
|
108
|
+
@_current_options = ::ActiveSupport::HashWithIndifferentAccess.new
|
109
|
+
@_current_options[:scope] = scope
|
110
|
+
@_current_options
|
111
|
+
end
|
112
|
+
|
113
|
+
def _current_rule_block
|
114
|
+
@_current_rule_block ||= []
|
115
|
+
end
|
116
|
+
|
117
|
+
def _reset_current_rule_block
|
118
|
+
@_current_rule_block = []
|
119
|
+
end
|
120
|
+
|
121
|
+
def _add_rule_to_current_rule_block(kind, *args)
|
122
|
+
opts = args.extract_options!
|
123
|
+
actions = _actions_from_options(args, opts)
|
124
|
+
roles = _roles_from_options(args, opts)
|
125
|
+
|
126
|
+
rule = ::Checkin::Rule.new(kind, :resources => _current_options[:resources], :roles => roles, :actions_or_attributes => actions, :scope => _current_options[:scope])
|
127
|
+
|
128
|
+
@_current_rule_block ||= []
|
129
|
+
@_current_rule_block << rule
|
130
|
+
|
131
|
+
rule
|
132
|
+
end
|
133
|
+
|
134
|
+
def _current_attributes_block
|
135
|
+
@_current_attributes_block ||= []
|
136
|
+
end
|
137
|
+
|
138
|
+
def _reset_current_attributes_block
|
139
|
+
@_current_attributes_block = []
|
140
|
+
end
|
141
|
+
|
142
|
+
def _add_rule_to_current_attributes_block(kind, *args)
|
143
|
+
opts = args.extract_options!
|
144
|
+
roles = _roles_from_options(args, opts)
|
145
|
+
|
146
|
+
rule = ::Checkin::Rule.new(kind, :resources => _current_options[:resources], :roles => roles, :actions_or_attributes => _current_options[:attributes], :scope => _current_options[:scope])
|
147
|
+
|
148
|
+
@_current_attributes_block ||= []
|
149
|
+
@_current_attributes_block << rule
|
150
|
+
|
151
|
+
rule
|
152
|
+
end
|
153
|
+
|
154
|
+
def _actions_from_options(args, opts)
|
155
|
+
[ opts[:to] ].flatten.compact.uniq.map {|a| "#{a}".to_sym}
|
156
|
+
end
|
157
|
+
|
158
|
+
def _roles_from_options(args, opts)
|
159
|
+
args.flatten.compact.uniq.map {|a| "#{a}".singularize.to_sym}
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# Author:: Maurizio Casimirri (mailto:maurizio.cas@gmail.com)
|
2
|
+
# Copyright:: Copyright (c) 2012 Maurizio Casimirri
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'checkin/role'
|
24
|
+
|
25
|
+
module Checkin
|
26
|
+
module Dsl
|
27
|
+
module Roles
|
28
|
+
extend ActiveSupport::Concern
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
|
32
|
+
def role(*args, &block)
|
33
|
+
opts = args.extract_options!
|
34
|
+
|
35
|
+
if args.empty?
|
36
|
+
raise ::ArgumentError.new("wrong number of arguments")
|
37
|
+
end
|
38
|
+
|
39
|
+
role_name = args.first
|
40
|
+
|
41
|
+
if role_name.to_s =~ /^can_([A-z]_)+\?$/
|
42
|
+
raise "bad role name: '#{role_name}'. Roles can not be in the form of 'can [...]?''"
|
43
|
+
end
|
44
|
+
|
45
|
+
if role_name.to_s.singularize != role_name.to_s
|
46
|
+
raise "bad role name: '#{role_name}'. Roles can not be in the plural form"
|
47
|
+
end
|
48
|
+
|
49
|
+
role = ::Checkin::Role.new
|
50
|
+
role.name = role_name
|
51
|
+
role.dependencies = [ opts[:require] ].flatten.compact.uniq
|
52
|
+
role.check_proc = block
|
53
|
+
role.aliases = ([ opts[:alias] ] + [ opts[:aliases] ]).flatten.compact.uniq.map {|a| "#{a.to_s.gsub(/\?$/, "")}?"}
|
54
|
+
role.check_method_name = "#{(opts[:method] || role_name).to_s.gsub(/\?$/, "")}?"
|
55
|
+
|
56
|
+
self.register_role(role)
|
57
|
+
end
|
58
|
+
|
59
|
+
def roles
|
60
|
+
@roles ||= ::ActiveSupport::HashWithIndifferentAccess.new
|
61
|
+
end
|
62
|
+
|
63
|
+
def role_methods
|
64
|
+
@role_methods ||= ::ActiveSupport::HashWithIndifferentAccess.new
|
65
|
+
end
|
66
|
+
|
67
|
+
def register_role(role)
|
68
|
+
|
69
|
+
self.register_role_method(role.check_method_name, role)
|
70
|
+
|
71
|
+
role.aliases.each do |a|
|
72
|
+
self.register_role_method(a, role)
|
73
|
+
end
|
74
|
+
|
75
|
+
self.roles[role.name] = role
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
def register_role_method(meth, role)
|
80
|
+
self.role_methods[meth] = role
|
81
|
+
end
|
82
|
+
|
83
|
+
def find_role_by_method(meth)
|
84
|
+
self.role_methods[meth]
|
85
|
+
end
|
86
|
+
|
87
|
+
def find_role_by_name(name)
|
88
|
+
self.roles[name]
|
89
|
+
end
|
90
|
+
|
91
|
+
def role_names
|
92
|
+
self.roles.keys.map {|k| k.to_s}
|
93
|
+
end
|
94
|
+
|
95
|
+
def symbolized_role_names
|
96
|
+
self.roles.keys.map {|k| k.to_sym}
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
def roles(*args)
|
102
|
+
roles = []
|
103
|
+
self.class.roles.each do |role_key, role|
|
104
|
+
roles << "#{role_key}".to_sym if check_role(role, *args)
|
105
|
+
end
|
106
|
+
roles
|
107
|
+
end
|
108
|
+
|
109
|
+
def role?(role, *args)
|
110
|
+
!!( check_role(role, *args) if (role = find_role_by_name(name)) )
|
111
|
+
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
def find_role_by_method(meth)
|
116
|
+
self.class.find_role_by_method(meth)
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_role_by_name(name)
|
120
|
+
self.class.find_role_by_name(name)
|
121
|
+
end
|
122
|
+
|
123
|
+
def is_role_method?(meth)
|
124
|
+
!!find_role_by_method(meth)
|
125
|
+
end
|
126
|
+
|
127
|
+
def check_role(role, *args)
|
128
|
+
|
129
|
+
roles_chain = role.dependencies.map{|d|
|
130
|
+
find_role_by_name(d) || (raise "required role not found '#{d}' for '#{role.name}")
|
131
|
+
} + [role]
|
132
|
+
|
133
|
+
roles_chain.each do |chain_role|
|
134
|
+
check_proc = chain_role.check_proc
|
135
|
+
check_args = args.slice(0, chain_role.check_proc.arity)
|
136
|
+
|
137
|
+
if !instance_exec(*check_args, &check_proc)
|
138
|
+
return false
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
true
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Checkin
|
2
|
+
module Filters
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
# checkin(:subject => :user, :scope => nil, :skip_authorization => false, :object => :object, rescue_with => lambda {
|
7
|
+
# if subject.guest?
|
8
|
+
# redirect_to new_user_session_path, :notice => "Accedi per completare l'operazione"
|
9
|
+
# else
|
10
|
+
# render :text => "Not Authorized", :status => 403
|
11
|
+
# end
|
12
|
+
# })
|
13
|
+
|
14
|
+
def checkin(opts = {})
|
15
|
+
opts.symbolize_keys!
|
16
|
+
from_subject = :"#{(opts[:subject] || :user_subject)}"
|
17
|
+
subject_name = :"#{(opts[:as] || :subject)}"
|
18
|
+
subject_model = :"#{(opts[:from] || :current_user)}"
|
19
|
+
subject_class = from_subject.to_s.camelize.constantize
|
20
|
+
object_method = :"#{(opts[:object] || :fetch_object)}"
|
21
|
+
find_method = opts[:find_object]
|
22
|
+
|
23
|
+
|
24
|
+
define_method "#{subject_name}" do
|
25
|
+
if !instance_variable_get("@checkin_#{subject_name}")
|
26
|
+
instance_variable_set("@checkin_#{subject_name}", subject_class.new(self.send(subject_model), :scope => opts[:scope]))
|
27
|
+
else
|
28
|
+
instance_variable_get("@checkin_#{subject_name}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
helper_method :"#{subject_name}"
|
33
|
+
|
34
|
+
if opts[:rescue_with]
|
35
|
+
block = opts[:rescue_with]
|
36
|
+
define_method :rescue_from_checkin_access_denied, &block
|
37
|
+
rescue_from Checkin::AccessDenied, :with => :rescue_from_checkin_access_denied
|
38
|
+
end
|
39
|
+
|
40
|
+
if !opts[:skip_authorization]
|
41
|
+
define_method :"#{object_method}" do
|
42
|
+
|
43
|
+
|
44
|
+
if params[:id]
|
45
|
+
model_class = self.controller_name.singularize.camelize.constantize
|
46
|
+
singular_name = :"#{model_class.name.underscore.singularize}"
|
47
|
+
if !instance_variable_get("@#{singular_name}")
|
48
|
+
find_method = if find_method.nil?
|
49
|
+
Proc.new {|model_class, params|
|
50
|
+
model_class.find(params[:id])
|
51
|
+
}
|
52
|
+
elsif find_method.is_a?(Proc) || find_method.is_a?(Method)
|
53
|
+
find_method
|
54
|
+
elsif find_method.is_a?(Symbol) || find_method.is_a?(String)
|
55
|
+
self.method(find_method)
|
56
|
+
else
|
57
|
+
raise "'#{find_method.class.name}' is an invalid type for find method"
|
58
|
+
end
|
59
|
+
instance_variable_set("@#{singular_name}", find_method.call(model_class, params))
|
60
|
+
else
|
61
|
+
instance_variable_get("@#{singular_name}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
before_filter do |controller|
|
67
|
+
if Rails.env.development?
|
68
|
+
controller.send(subject_name).explain!
|
69
|
+
end
|
70
|
+
controller.send(subject_name).checkin!( :"#{controller.action_name}", (controller.send(:"#{object_method}") || {:for => :"#{controller.controller_name}"}) )
|
71
|
+
controller.send(subject_name).delete_denied_params( :"#{controller.action_name}", (controller.send(:"#{object_method}") || {:for => :"#{controller.controller_name}"}), (params[:"#{controller.controller_name.singularize}"] || {}) )
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
data/lib/checkin/role.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Author:: Maurizio Casimirri (mailto:maurizio.cas@gmail.com)
|
2
|
+
# Copyright:: Copyright (c) 2012 Maurizio Casimirri
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
class Checkin::Role
|
24
|
+
attr_accessor :name, :dependencies, :check_proc, :aliases, :check_method_name
|
25
|
+
end
|
26
|
+
|
data/lib/checkin/rule.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# Author:: Maurizio Casimirri (mailto:maurizio.cas@gmail.com)
|
2
|
+
# Copyright:: Copyright (c) 2012 Maurizio Casimirri
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
class Checkin::Rule
|
24
|
+
attr_accessor :kind, :actions_or_attributes, :roles, :resources, :scope
|
25
|
+
|
26
|
+
def initialize(kind, *args)
|
27
|
+
opts = args.extract_options!
|
28
|
+
@kind = kind
|
29
|
+
@actions_or_attributes = (opts[:actions_or_attributes] || []).map {|a| "#{a}".to_sym }
|
30
|
+
@roles = (opts[:roles] || []).map {|r| "#{r}".to_sym }
|
31
|
+
@resources = (opts[:resources] || []).map {|r| "#{r}".singularize.to_sym }
|
32
|
+
@scope = opts[:scope].present? ? opts[:scope].to_sym : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def check(subject, action_or_attribute, object_or_resource)
|
36
|
+
scope = subject.scope
|
37
|
+
action = "#{action}".to_sym
|
38
|
+
|
39
|
+
object_or_resource = object_or_resource[:for] if object_or_resource.is_a?(Hash)
|
40
|
+
object = ( object_or_resource.is_a?(Symbol) || object_or_resource.is_a?(String)) ? nil : object_or_resource
|
41
|
+
resource = object ? object.class.name.demodulize.underscore.to_sym : "#{object_or_resource}".singularize.to_sym
|
42
|
+
|
43
|
+
if affect_scope?(scope) && affect_role?(subject, object) && affect_action_or_attribute?(action_or_attribute) && affect_resource?(resource)
|
44
|
+
deny? ? :denied : :allowed
|
45
|
+
else
|
46
|
+
:skip
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
formatted_roles = roles.map {|r| ":#{r}" }.join(", ") if roles.any?
|
52
|
+
formatted_actions = ":to => [" + actions_or_attributes.map {|a| ":#{a}" }.join(", ") + "]" if actions_or_attributes.any?
|
53
|
+
formatted_scope = ":scope => :#{scope}" if scope
|
54
|
+
formatted_resources = ":resources => [" + actions_or_attributes.map {|r| ":#{r}" }.join(", ") + "]" if resources.any?
|
55
|
+
args = [formatted_roles, formatted_actions, formatted_resources, formatted_scope].compact.join(", ")
|
56
|
+
"#{kind}(#{args})"
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def affect_scope?(scope)
|
62
|
+
scope && ( any_scope? || @scope == scope.to_sym )
|
63
|
+
end
|
64
|
+
|
65
|
+
def affect_role?(subject, object)
|
66
|
+
args = [object].compact
|
67
|
+
any_role? || (subject.roles(*args) & @roles).any?
|
68
|
+
end
|
69
|
+
|
70
|
+
def affect_action_or_attribute?(action_or_attribute)
|
71
|
+
any_action_or_attribute? || @actions_or_attributes.include?(action_or_attribute)
|
72
|
+
end
|
73
|
+
|
74
|
+
def affect_resource?(resource)
|
75
|
+
any_resource? || @resources.include?(resource)
|
76
|
+
end
|
77
|
+
|
78
|
+
def any_role?
|
79
|
+
!!@roles.empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
def any_action_or_attribute?
|
83
|
+
!!@actions_or_attributes.empty?
|
84
|
+
end
|
85
|
+
|
86
|
+
def any_scope?
|
87
|
+
@scope.blank?
|
88
|
+
end
|
89
|
+
|
90
|
+
def any_resource?
|
91
|
+
!!@resources.empty?
|
92
|
+
end
|
93
|
+
|
94
|
+
def deny?
|
95
|
+
@kind == :deny
|
96
|
+
end
|
97
|
+
|
98
|
+
def allow?
|
99
|
+
@kind == :allow
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# Author:: Maurizio Casimirri (mailto:maurizio.cas@gmail.com)
|
2
|
+
# Copyright:: Copyright (c) 2012 Maurizio Casimirri
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'checkin/dsl/roles'
|
24
|
+
require 'checkin/dsl/permissions'
|
25
|
+
|
26
|
+
class Checkin::Subject
|
27
|
+
include ::Checkin::Dsl::Roles
|
28
|
+
include ::Checkin::Dsl::Permissions
|
29
|
+
|
30
|
+
def initialize(subject_model, scope = {})
|
31
|
+
@subject_model = subject_model
|
32
|
+
@scope = scope[:scope]
|
33
|
+
end
|
34
|
+
|
35
|
+
def subject_model
|
36
|
+
@subject_model
|
37
|
+
end
|
38
|
+
|
39
|
+
def scope
|
40
|
+
:"#{@scope}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def can?(action, object_or_resource)
|
44
|
+
|
45
|
+
if @explain
|
46
|
+
Rails.logger.info " + can?(:#{action}, #{object_or_resource})"
|
47
|
+
end
|
48
|
+
|
49
|
+
self.class.rules.each do|rule|
|
50
|
+
result = rule.check(self, :"#{action}", object_or_resource)
|
51
|
+
|
52
|
+
if @explain
|
53
|
+
Rails.logger.info [" - #{rule}".ljust(65), ":#{result}"].join(" => ")
|
54
|
+
end
|
55
|
+
|
56
|
+
case result
|
57
|
+
when :denied
|
58
|
+
return false
|
59
|
+
when :allowed
|
60
|
+
return true
|
61
|
+
else
|
62
|
+
end
|
63
|
+
end
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def allowed_to_set?(attribute, on = {})
|
68
|
+
|
69
|
+
object = on[:on]
|
70
|
+
if @explain
|
71
|
+
Rails.logger.info " + allowed_to_set?(:#{attribute}, on => #{object})"
|
72
|
+
end
|
73
|
+
|
74
|
+
self.class.attribute_rules.each do|rule|
|
75
|
+
result = rule.check(self, :"#{attribute}", object)
|
76
|
+
|
77
|
+
if @explain
|
78
|
+
Rails.logger.info [" - #{rule}".ljust(65), ":#{result}"].join(" => ")
|
79
|
+
end
|
80
|
+
|
81
|
+
case result
|
82
|
+
when :denied
|
83
|
+
return false
|
84
|
+
when :allowed
|
85
|
+
return true
|
86
|
+
else
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
def explain!
|
94
|
+
@explain = true
|
95
|
+
end
|
96
|
+
|
97
|
+
def stop_explaining!
|
98
|
+
@explain = false
|
99
|
+
end
|
100
|
+
|
101
|
+
def checkin!(action, object_or_resource)
|
102
|
+
raise Checkin::AccessDenied.new(self, action, object_or_resource) unless self.can?(action, object_or_resource)
|
103
|
+
end
|
104
|
+
|
105
|
+
def delete_denied_params(action, object_or_resource, resource_params)
|
106
|
+
to_be_deleted = []
|
107
|
+
resource_params.keys.each {|key|
|
108
|
+
to_be_deleted.push(key) unless self.allowed_to_set?(key, :on => object_or_resource)
|
109
|
+
}
|
110
|
+
to_be_deleted.each do |key_to_delete|
|
111
|
+
resource_params.delete(key_to_delete)
|
112
|
+
end
|
113
|
+
resource_params
|
114
|
+
end
|
115
|
+
|
116
|
+
def method_missing(mid, *args)
|
117
|
+
missing_method = mid.to_s
|
118
|
+
prefixed_with_can = (missing_method =~ /^can_/) && (missing_method =~ /\?$/)
|
119
|
+
|
120
|
+
if prefixed_with_can
|
121
|
+
action = missing_method.gsub(/^can_/, "").gsub(/\?$/, "")
|
122
|
+
self.can?(action, *args)
|
123
|
+
|
124
|
+
elsif self.respond_to?(:"is_role_method?") && self.is_role_method?(missing_method)
|
125
|
+
role = self.find_role_by_method(missing_method)
|
126
|
+
self.check_role(role, *args)
|
127
|
+
|
128
|
+
elsif @subject_model && @subject_model.respond_to?(missing_method)
|
129
|
+
@subject_model.send(missing_method, *args)
|
130
|
+
|
131
|
+
else
|
132
|
+
raise NoMethodError.new("undefined method `#{missing_method}' for #{self.class.name}")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
data/lib/checkin.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Author:: Maurizio Casimirri (mailto:maurizio.cas@gmail.com)
|
2
|
+
# Copyright:: Copyright (c) 2012 Maurizio Casimirri
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
23
|
+
module Checkin
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'checkin/filters'
|
27
|
+
require 'checkin/subject'
|
28
|
+
require 'checkin/access_denied'
|
29
|
+
|
30
|
+
class ActionController::Base
|
31
|
+
include Checkin::Filters
|
32
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'checkin'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: checkin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- mcasimir
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: jeweler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.8.3
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.8.3
|
30
|
+
description: Checkin is an authorization gem for Ruby on Rails
|
31
|
+
email: maurizio.cas@gmail.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files:
|
35
|
+
- LICENSE.txt
|
36
|
+
- README.md
|
37
|
+
files:
|
38
|
+
- .document
|
39
|
+
- Gemfile
|
40
|
+
- Gemfile.lock
|
41
|
+
- LICENSE.txt
|
42
|
+
- README.md
|
43
|
+
- Rakefile
|
44
|
+
- VERSION
|
45
|
+
- checkin.gemspec
|
46
|
+
- lib/checkin.rb
|
47
|
+
- lib/checkin/access_denied.rb
|
48
|
+
- lib/checkin/dsl/permissions.rb
|
49
|
+
- lib/checkin/dsl/roles.rb
|
50
|
+
- lib/checkin/filters.rb
|
51
|
+
- lib/checkin/role.rb
|
52
|
+
- lib/checkin/rule.rb
|
53
|
+
- lib/checkin/subject.rb
|
54
|
+
- test/helper.rb
|
55
|
+
- test/test_checkin.rb
|
56
|
+
homepage: http://github.com/mcasimir/checkin
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
hash: 1307085424481181596
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.8.24
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: Checkin is an authorization gem for Ruby on Rails
|
84
|
+
test_files: []
|