simple_acl 1.0.0
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/README.md +95 -0
- data/lib/simple_acl.rb +76 -0
- data/lib/simple_acl/acl.rb +46 -0
- data/lib/simple_acl/configuration.rb +58 -0
- data/lib/simple_acl/exceptions.rb +6 -0
- data/lib/simple_acl/version.rb +3 -0
- metadata +67 -0
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# SimpleAcl
|
2
|
+
|
3
|
+
[](https://travis-ci.org/ifeelgoods/simple_acl)
|
4
|
+
|
5
|
+
This gem eases the implementation of ACL in Ruby (especially Rails).
|
6
|
+
|
7
|
+
All access are refused is only rule by default.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'simple_acl'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
You need to include the main module:
|
22
|
+
|
23
|
+
`include SimpleAcl`
|
24
|
+
|
25
|
+
SimpleAcl need 3 variables:
|
26
|
+
- the action : by default use `params[:action]` if available, nil otherwise
|
27
|
+
- the role : by default use method `current_role` if available, nil otherwise
|
28
|
+
- optional values for custom assertion : by default use `params` if available, nil otherwise
|
29
|
+
|
30
|
+
You can manually define these by using following methods in the controller:
|
31
|
+
`acl_current_role=` `acl_action=` `acl_values=`
|
32
|
+
|
33
|
+
Use the following before_filter to check ACL before the
|
34
|
+
execution of the code in the action.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
before_filter :do_acl
|
38
|
+
```
|
39
|
+
|
40
|
+
## Configuration
|
41
|
+
|
42
|
+
To configure the ability of a role you can use:
|
43
|
+
|
44
|
+
`acl_user, acl_admin, acl_guest`
|
45
|
+
|
46
|
+
or the basic method `acl_role` with which you need to specify the role.
|
47
|
+
|
48
|
+
The key `privileges` must be a hash of assertions.
|
49
|
+
The key `inherit` must be the symbol of previous defined role.
|
50
|
+
|
51
|
+
Example:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
acl_user privileges: {
|
55
|
+
index: true,
|
56
|
+
show: true,
|
57
|
+
show_from_adserver_affiliate_id: true
|
58
|
+
}
|
59
|
+
|
60
|
+
acl_admin inherit: :user
|
61
|
+
```
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
acl_role(:guest, show: true)
|
65
|
+
```
|
66
|
+
|
67
|
+
If the role trying to access to the resource is not allowed a ExceptionUnauthorized
|
68
|
+
exception will be raised.
|
69
|
+
Catch it to render/do whatever you want in this case:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
rescue_from ExceptionUnauthorized do
|
73
|
+
# render 403
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
In an initializers, you can specify the role you want to use.
|
78
|
+
(defaults are :admin, :user, :guest)
|
79
|
+
|
80
|
+
```
|
81
|
+
SimpleAcl::Configuration.authorized_roles = [:admin, :user]
|
82
|
+
|
83
|
+
```
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
1. Fork it
|
88
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
89
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
90
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
91
|
+
5. Create new Pull Request
|
92
|
+
|
93
|
+
Inspired from `racl-rails` and `racl`.
|
94
|
+
https://github.com/ifeelgoods/racl/
|
95
|
+
https://github.com/ifeelgoods/racl-rails/
|
data/lib/simple_acl.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'simple_acl/acl'
|
2
|
+
require 'simple_acl/exceptions'
|
3
|
+
|
4
|
+
module SimpleAcl
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
def acl
|
12
|
+
@acl ||= Acl.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def acl_user(privileges)
|
16
|
+
role_acl(:user, privileges)
|
17
|
+
end
|
18
|
+
|
19
|
+
def acl_admin(privileges)
|
20
|
+
role_acl(:admin, privileges)
|
21
|
+
end
|
22
|
+
|
23
|
+
def acl_guest(privileges)
|
24
|
+
role_acl(:guest, privileges)
|
25
|
+
end
|
26
|
+
|
27
|
+
def role_acl(role, privileges)
|
28
|
+
acl.configuration.add_role(role, privileges)
|
29
|
+
end
|
30
|
+
|
31
|
+
def acl_to_json
|
32
|
+
acl.configuration.acl_privileges.to_json
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param values used for custom lambda assertion
|
37
|
+
def acl_values=(values)
|
38
|
+
Thread.current[:acl_values] = values
|
39
|
+
end
|
40
|
+
|
41
|
+
def acl_values
|
42
|
+
Thread.current[:acl_values] ||= defined?(params) ? params : nil
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param current_role used for the assertion
|
46
|
+
def acl_current_role=(current_role)
|
47
|
+
Thread.current[:acl_current_role] = current_role
|
48
|
+
end
|
49
|
+
|
50
|
+
def acl_current_role
|
51
|
+
Thread.current[:acl_current_role] ||= defined?(current_role) ? current_role : nil
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param action used for the assertion
|
55
|
+
def acl_action=(action)
|
56
|
+
Thread.current[:acl_action] = action
|
57
|
+
end
|
58
|
+
|
59
|
+
def acl_action
|
60
|
+
Thread.current[:acl_action] ||= (defined?(params) && params.is_a?(Hash)) ? params[:action] : nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return True is success, raise ExceptionUnauthorized otherwise
|
64
|
+
def do_acl
|
65
|
+
return Acl.unauthorized unless self.class.acl
|
66
|
+
|
67
|
+
begin
|
68
|
+
self.class.acl.check_acl(acl_current_role, params[:action], acl_values)
|
69
|
+
ensure
|
70
|
+
# in case of Thread,current is not cleaned
|
71
|
+
Thread.current[:acl_action] = nil
|
72
|
+
Thread.current[:acl_current_role] = nil
|
73
|
+
Thread.current[:acl_values] = nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'simple_acl/configuration'
|
2
|
+
|
3
|
+
module SimpleAcl
|
4
|
+
class Acl
|
5
|
+
|
6
|
+
attr_reader :configuration
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@configuration = Configuration.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def check_acl(current_role, action, values)
|
13
|
+
|
14
|
+
return self.class.unauthorized unless configuration && current_role
|
15
|
+
|
16
|
+
role_privileges = configuration.acl_privileges[current_role.to_sym]
|
17
|
+
|
18
|
+
return self.class.unauthorized unless role_privileges
|
19
|
+
|
20
|
+
assertion = role_privileges[action.to_sym]
|
21
|
+
|
22
|
+
self.class.assert(assertion, current_role, values)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.assert(assertion, current_role, values)
|
26
|
+
|
27
|
+
return authorized if assertion.class == TrueClass
|
28
|
+
|
29
|
+
if assertion.class == Proc && assertion.lambda?
|
30
|
+
assertion_result = assertion.call(current_role, values)
|
31
|
+
return assert(assertion_result, current_role, values)
|
32
|
+
end
|
33
|
+
|
34
|
+
unauthorized
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.unauthorized
|
38
|
+
raise ExceptionUnauthorized
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.authorized
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module SimpleAcl
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
class << self
|
5
|
+
attr_writer :authorized_roles
|
6
|
+
|
7
|
+
def authorized_roles
|
8
|
+
@authorized_roles ||= [:admin, :user, :guest]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :acl_privileges
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@acl_privileges = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_role(role, privileges)
|
19
|
+
raise ExceptionConfiguration, ExceptionConfiguration, "Unauthorized role #{role}" unless self.class.authorized_roles.include?(role)
|
20
|
+
privileges.keys.each do |configuration_key|
|
21
|
+
raise ExceptionConfiguration, "Unknow configuration key #{configuration_key}" unless [:privileges, :inherit].include?(configuration_key)
|
22
|
+
end
|
23
|
+
raise ExceptionConfiguration, 'Inherit specified is not defined previously' if privileges[:inherit] && !@acl_privileges[privileges[:inherit]]
|
24
|
+
|
25
|
+
@acl_privileges[role] = (@acl_privileges[privileges[:inherit]] || {}).merge(privileges[:privileges] || {})
|
26
|
+
|
27
|
+
check_set_up(@acl_privileges[role])
|
28
|
+
|
29
|
+
deep_freeze!(@acl_privileges[role])
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# check of the set up
|
35
|
+
def check_set_up(privileges)
|
36
|
+
privileges.keys.each{|action| check_assertion(privileges[action]) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_assertion(assertion)
|
40
|
+
return if assertion.class == Proc && assertion.lambda?
|
41
|
+
raise ExceptionConfiguration, "Not usable assertion type : #{assertion.class}" unless [TrueClass, FalseClass].include?(assertion.class)
|
42
|
+
end
|
43
|
+
|
44
|
+
# do a recursive freeze on Array and Hash
|
45
|
+
def deep_freeze!(option)
|
46
|
+
option.freeze
|
47
|
+
|
48
|
+
case option.class
|
49
|
+
when Hash
|
50
|
+
option.each{|k, v| deep_freeze(option[k]) }
|
51
|
+
when Array
|
52
|
+
option.each{|v| deep_freeze(v) }
|
53
|
+
else
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_acl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- mtparet
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.14'
|
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: '2.14'
|
30
|
+
description: Simple Gem to use ACL in ruby (and especially in Rails) based on a role
|
31
|
+
given. Great use with Devise.
|
32
|
+
email: tech@ifeelgoods.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- README.md
|
38
|
+
- lib/simple_acl/acl.rb
|
39
|
+
- lib/simple_acl/version.rb
|
40
|
+
- lib/simple_acl/configuration.rb
|
41
|
+
- lib/simple_acl/exceptions.rb
|
42
|
+
- lib/simple_acl.rb
|
43
|
+
homepage: https://github.com/ifeelgoods/simple_acl
|
44
|
+
licenses: []
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.8.25
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Simple Gem to implement ACL in Rails based on a role given.
|
67
|
+
test_files: []
|