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 ADDED
@@ -0,0 +1,95 @@
1
+ # SimpleAcl
2
+
3
+ [![Build Status](https://travis-ci.org/ifeelgoods/simple_acl.png?branch=master)](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
@@ -0,0 +1,6 @@
1
+ module SimpleAcl
2
+ class ExceptionUnauthorized < Exception
3
+ end
4
+ class ExceptionConfiguration < Exception
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleAcl
2
+ VERSION = '1.0.0'
3
+ 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: []