flexible_accessibility 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flexible_accessibility (0.3.2)
4
+ flexible_accessibility (0.3.3)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -8,17 +8,43 @@ Installation:
8
8
 
9
9
  or add to your Gemfile
10
10
 
11
- gem 'flexible_accessibility', '0.3.2'
11
+ gem 'flexible_accessibility', '0.3.3'
12
12
 
13
- Do
13
+ then do
14
14
 
15
- rails g flexible_accessibility:install
15
+ rails g flexible_accessibility:install
16
16
 
17
17
  to install migrations
18
18
 
19
+ Usage:
20
+
21
+ All routes in application are closed by default
22
+ To add route for check or open it you have to use 'authorize' macro in your controller
23
+ The macro has a couple of options:
24
+
25
+ Add all routes to check:
26
+
27
+ authorize :all
28
+
29
+ Add some routes to check but close all others
30
+
31
+ authorize :only => [:index, :new]
32
+
33
+ Add all routes except :index to check, :index remains closed
34
+
35
+ authorize :except => [:index]
36
+
37
+ Add :index and :new to check, skip (open) create for all
38
+
39
+ authorize :only => [:index, :new], :skip => [:create]
40
+
41
+ Open all routes for all
42
+
43
+ authorize :skip => :all
44
+
19
45
  ======================
20
46
 
21
47
  ## Copyright
22
- Copyright (c) 2012-2013 Sergey Avanesov and 7 Pikes, Inc.
48
+ Copyright (c) 2012-2014 Sergey Avanesov and 7 Pikes, Inc.
23
49
 
24
50
  ![7pikes logo](https://github.com/7Pikes/flexible_accessibility/wiki/Logo.png)
@@ -2,9 +2,9 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'flexible_accessibility'
5
- s.version = '0.3.2'
5
+ s.version = '0.3.3'
6
6
  s.authors = ['Sergey Avanesov']
7
- s.date = '2013-09-30'
7
+ s.date = '2014-01-08'
8
8
  s.summary = 'Flexible access control system'
9
9
  s.description = 'Flexible access control system for your rails application. Based on analysis of controller actions'
10
10
  s.email = 'sergey.awanesov@gmail.com'
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.files = `git ls-files`.split("\n")
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
17
 
18
- s.rubygems_version = "1.8.24"
18
+ s.rubygems_version = '1.8.24'
19
19
  s.required_rubygems_version = Gem::Requirement.new('> 1.3.1') if s.respond_to? :required_rubygems_version=
20
20
 
21
21
  s.add_development_dependency 'i18n'
@@ -4,39 +4,54 @@ module FlexibleAccessibility
4
4
 
5
5
  # Compatibility with previous versions
6
6
  def skip_authorization_here
7
- not_authorize :all
8
- end
9
-
10
- # Macro for define actions without authorization
11
- def not_authorize(args={})
12
- valid_arguments = parse_and_validate_arguments(args)
13
- self.instance_variable_set(:@_non_verifiable_routes, self.action_methods) if valid_arguments[:all]
14
- self.instance_variable_set(:@_non_verifiable_routes, valid_arguments[:only]) unless valid_arguments[:only].nil?
15
- self.instance_variable_set(:@_verifiable_routes, []) if self.instance_variable_get(:@_non_verifiable_routes).nil?
7
+ authorize :skip => :all
16
8
  end
17
9
 
18
10
  # Macro for define actions with authorization
19
11
  def authorize(args={})
20
- valid_arguments = parse_and_validate_arguments(args)
21
- self.instance_variable_set(:@_verifiable_routes, valid_arguments[:only]) unless valid_arguments[:only].nil?
22
- self.instance_variable_set(:@_verifiable_routes, self.action_methods - valid_arguments[:except]) unless valid_arguments[:except].nil?
23
- self.instance_variable_set(:@_verifiable_routes, self.action_methods) if valid_arguments[:all]
24
- self.instance_variable_set(:@_non_verifiable_routes, []) if self.instance_variable_get(:@_non_verifiable_routes).nil?
12
+ arguments = parse_arguments(args)
13
+ validate_arguments(arguments)
14
+ available_routes = Utils.new.app_routes[self.to_s.gsub(/Controller/, '')]
15
+ available_routes = available_routes.to_set unless available_routes.nil?
16
+ unless available_routes.nil?
17
+ self.instance_variable_set(:@_verifiable_routes, available_routes) if arguments[:all]
18
+ self.instance_variable_set(:@_verifiable_routes, arguments[:only]) unless arguments[:only].nil?
19
+ self.instance_variable_set(:@_verifiable_routes, available_routes - arguments[:except]) unless arguments[:except].nil?
20
+ unless arguments[:skip].nil?
21
+ non_verifiable_routes = arguments[:skip].first == 'all' ? available_routes : arguments[:skip]
22
+ self.instance_variable_set(:@_non_verifiable_routes, non_verifiable_routes)
23
+ end
24
+ end
25
25
  end
26
26
 
27
27
  private
28
28
  # Parse arguments from macro calls
29
- def parse_and_validate_arguments(args={})
29
+ def parse_arguments(args={})
30
30
  result = {}
31
- (result[:all] = true) and return result if args.to_s == 'all'
32
- [:only, :except].each do |key|
31
+ (result[:all] = ['all'].to_set) and return result if args.to_s == 'all'
32
+ [:only, :except, :skip].each do |key|
33
33
  unless args[key].nil?
34
+ result[key] = [args[key].to_s].to_set and next if args[key].to_s == 'all' && key == :skip
34
35
  raise ActionsValueException unless args[key].instance_of?(Array)
35
36
  result[key] = args[key].map!{ |v| v.to_s }.to_set
36
37
  end
37
38
  end
38
39
  result
39
40
  end
41
+
42
+ def validate_arguments(args={})
43
+ return if args.count == 1 && args.keys.include?(:all)
44
+ only_options = args[:only] || Set.new
45
+ except_options = args[:except] || Set.new
46
+ skip_options = args[:skip] || Set.new
47
+ unless (only_options & except_options).empty? &&
48
+ (only_options & skip_options).empty?
49
+ raise IncorrectArgumentException.new(nil, 'The same arguments shouldn\'t be used with different keys excluding except and skip')
50
+ end
51
+ if args[:skip] == 'all' && args.count > 1
52
+ raise IncorrectArgumentException.new(nil, 'Option \'skip\' with argument \'all\' shouldn\'t be used with another options')
53
+ end
54
+ end
40
55
  end
41
56
 
42
57
  # Callback is needed for include methods and define helper method
@@ -1,6 +1,6 @@
1
1
  module FlexibleAccessibility
2
2
  class FlexibleAccessibilityException < StandardError
3
- attr_reader :action, :subject, :default_message
3
+ attr_reader :action, :subject
4
4
 
5
5
  def initialize(action = nil, subject = nil)
6
6
  @action = action
@@ -8,71 +8,84 @@ module FlexibleAccessibility
8
8
  end
9
9
 
10
10
  def to_s
11
- message || default_message
11
+ message || default_message || @subject
12
12
  end
13
13
 
14
- private
15
14
  def message
16
- nil
15
+ @subject || nil
17
16
  end
18
17
 
18
+ private
19
19
  def default_message
20
20
  'An exception is occurred'
21
21
  end
22
22
  end
23
23
 
24
24
  class AccessDeniedException < FlexibleAccessibilityException
25
- private
25
+
26
26
  def message
27
27
  I18n.t('flexible_accessibility.errors.access_denied', :action => @action)
28
28
  end
29
29
 
30
+ private
30
31
  def default_message
31
32
  "The access for resource #{@action} is denied"
32
33
  end
33
34
  end
34
35
 
35
36
  class UserNotLoggedInException < FlexibleAccessibilityException
36
- private
37
+
37
38
  def message
38
39
  I18n.t('flexible_accessibility.errors.user_is_not_logged_in')
39
40
  end
40
41
 
42
+ private
41
43
  def default_message
42
44
  'Current user is not logged in'
43
45
  end
44
46
  end
45
47
 
46
48
  class NoWayToDetectLoggerUserException < FlexibleAccessibilityException
47
- private
49
+
48
50
  def message
49
51
  I18n.t('flexible_accessibility.errors.no_way_to_detect_logged_user')
50
52
  end
51
53
 
54
+ private
52
55
  def default_message
53
56
  'No way to detect a logged user - may you have forgot to define a current_user helper'
54
57
  end
55
58
  end
56
59
 
57
60
  class UnknownUserException < FlexibleAccessibilityException
58
- private
61
+
59
62
  def message
60
63
  I18n.t('flexible_accessibility.errors.unknown_user')
61
64
  end
62
65
 
66
+ private
63
67
  def default_message
64
68
  'Probably you have forgot to send a user in has_access?'
65
69
  end
66
70
  end
67
71
 
68
72
  class ActionsValueException < FlexibleAccessibilityException
69
- private
73
+
70
74
  def message
71
75
  I18n.t('flexible_accessibility.errors.incorrect_value_of_actions')
72
76
  end
73
77
 
78
+ private
74
79
  def default_message
75
80
  'The value of any \'authorize\' macro argument should be declared as Array'
76
81
  end
77
82
  end
83
+
84
+ class IncorrectArgumentException < FlexibleAccessibilityException
85
+
86
+ private
87
+ def default_message
88
+ nil
89
+ end
90
+ end
78
91
  end
@@ -31,14 +31,17 @@ module FlexibleAccessibility
31
31
 
32
32
  # Check access to route and we expected the existing of current_user helper
33
33
  def check_permission_to_route
34
+ self.class.instance_variable_set(:@_verifiable_routes, []) if self.class.instance_variable_get(:@_verifiable_routes).nil?
35
+ self.class.instance_variable_set(:@_non_verifiable_routes, []) if self.class.instance_variable_get(:@_non_verifiable_routes).nil?
36
+
34
37
  if self.class.instance_variable_get(:@_verifiable_routes).include?(current_action)
35
38
  raise UserNotLoggedInException.new(current_route, nil) if logged_user.nil?
36
- self.class.instance_variable_set(:@_route_permitted, AccessProvider.is_action_permitted_for_user?(current_route, logged_user))
39
+ self.class.instance_variable_set(:@_route_permitted, AccessProvider.is_action_permitted_for_user?(current_route, logged_user))
37
40
  elsif self.class.instance_variable_get(:@_non_verifiable_routes).include? current_action
38
41
  self.class.instance_variable_set(:@_route_permitted, true)
39
42
  else
40
43
  self.class.instance_variable_set(:@_route_permitted, false)
41
- end
44
+ end
42
45
  end
43
46
 
44
47
  def allow_route
@@ -20,11 +20,11 @@ module FlexibleAccessibility
20
20
  class << self
21
21
  def all
22
22
  permissions = []
23
- Utils.new.get_controllers.each do |scope|
23
+ Utils.new.app_controllers.each do |scope|
24
24
  namespace = scope.first.to_s
25
25
  scope.last.each do |resource|
26
- resource = "#{namespace}/#{resource}" unless namespace == "default"
27
- permissions << Permission.new(:resource => resource.gsub(/_controller/, ""), :actions => ApplicationResource.new(resource).klass.instance_variable_get(:@_verifiable_routes))
26
+ resource = "#{namespace}/#{resource}" unless namespace == 'default'
27
+ permissions << Permission.new(:resource => resource.gsub(/_controller/, ''), :actions => ApplicationResource.new(resource).klass.instance_variable_get(:@_verifiable_routes))
28
28
  end
29
29
  end
30
30
  permissions
@@ -1,19 +1,27 @@
1
1
  module FlexibleAccessibility
2
2
  class Utils
3
+ @@routes ||= {}
4
+
3
5
  def initialize
4
6
  @path = "#{::Rails.root}/app/controllers/"
5
7
  @controllers = {}
6
8
  end
7
9
 
8
- def get_controllers
9
- get_controllers_recursive(@path)
10
+ def app_controllers
11
+ app_controllers_recursive(@path)
12
+ end
13
+
14
+ def app_routes
15
+ app_routes_as_hash if @@routes.empty?
16
+ @@routes
10
17
  end
11
18
 
19
+ private
12
20
  # All controller classes placed in :default scope
13
- def get_controllers_recursive(path)
21
+ def app_controllers_recursive(path)
14
22
  (Dir.new(path).entries - ['..', '.']).each do |entry|
15
23
  if File.directory?(path + entry)
16
- get_controllers_recursive(path + entry + '/')
24
+ app_controllers_recursive(path + entry + '/')
17
25
  else
18
26
  parent_directory = File.dirname(path + entry).split(/\//).last
19
27
  container = parent_directory == 'controllers' ? 'default' : parent_directory
@@ -23,5 +31,17 @@ module FlexibleAccessibility
23
31
  end
24
32
  @controllers
25
33
  end
34
+
35
+ # Routes from routes.rb
36
+ def app_routes_as_hash
37
+ Rails.application.routes.routes.each do |route|
38
+ controller = route.defaults[:controller]
39
+ unless controller.nil?
40
+ key = controller.split('/').map { |p| p.camelize }.join('::')
41
+ @@routes[key] ||= []
42
+ @@routes[key] << route.defaults[:action]
43
+ end
44
+ end
45
+ end
26
46
  end
27
47
  end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: flexible_accessibility
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.2
5
+ version: 0.3.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Sergey Avanesov
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-30 00:00:00.000000000 Z
12
+ date: 2014-01-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  prerelease: false