right_on 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 47a774795b314e80b1177664e0cd976febaa14c1
4
- data.tar.gz: cf508fd4630a43d912fd91a9d9b1efa3b7167fdf
2
+ SHA256:
3
+ metadata.gz: 3ed9eb070b0aac90604d39af448f24eb80f69d1c7b43e70262ff163ebeb9b414
4
+ data.tar.gz: 5645724ce29fb1167685bb8413b73c487313bd4c285d16ff879043eac3b5dc4b
5
5
  SHA512:
6
- metadata.gz: d43bab3c7da9f1b0828b15f1ec2e1c8101d2dfa9d39e36cc2915fbb09af250a8cd86582e940bf743ff06a4b20ccbd3347f1d7f528da5cc6b21f21a1741794478
7
- data.tar.gz: abb42ecc1c3d731988a07b007a87d2bb7088550cab5627835b5426bc806e239b068b04c1bd91dc53e07562f463c671c2b78c8edf7e50d9fd825a79549d5eb419
6
+ metadata.gz: de53dd0a3448bc3ed57e1621b179a4333c63f976f240f88812e0639c8cd7478ca10efef8cd3df2660ece487e9409f459e14147455d86a89590028c3588c7a8d5
7
+ data.tar.gz: 0c8836a459c9073b6b38d01efcbc5ca6e533405dc6efde62f462eba10cf8920fe1ba20c29c3703d647a9399cbaedcc68de34f392911c983776e0b0d53676f8c6
@@ -0,0 +1,2 @@
1
+ ruby:
2
+ config_file: .rubocop.yml
@@ -0,0 +1,5 @@
1
+ Style/StringLiterals:
2
+ EnforcedStyle: single_quotes
3
+ SupportedStyles:
4
+ - single_quotes
5
+ - double_quotes
@@ -1,11 +1,14 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3.0
3
+ - 2.3
4
+ - 2.4
5
+ - 2.5
4
6
  script: "bundle exec rake spec"
5
7
  gemfile:
6
- - gemfiles/rails3.gemfile
7
8
  - gemfiles/rails4.gemfile
8
9
  - gemfiles/rails5.gemfile
10
+ # fix ruby 2.5 issue - https://github.com/travis-ci/travis-ci/issues/9333
11
+ before_install: gem install bundler
9
12
  notifications:
10
13
  email:
11
14
  - support@travellink.com.au
@@ -5,6 +5,19 @@ This changelog adheres to [Keep a CHANGELOG](http://keepachangelog.com/).
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 0.4.0
9
+
10
+ ### Improved
11
+ - Improve tests for RightOn::ByGroup
12
+ - Internal improvement of RightOn::ByGroup
13
+ - Internal extraction of 'allowed?' feature for failure message
14
+ - CanCanRight functionality merged into RightOn
15
+ - Cleanup of CanCanRight/RightOn merge
16
+
17
+ ### Fixed
18
+ - [TT-3352] Ensure roles currently in use cannot be deleted
19
+ - Also dropped rails 3 support due to above
20
+
8
21
  ## 0.3.0
9
22
 
10
23
  ### Fixed
@@ -1,23 +1,23 @@
1
1
  class RightOnMigration < ActiveRecord::Migration
2
2
  def self.change
3
3
  create_table :rights do |t|
4
- t.string :name, :controller, :action, :limit => 150
4
+ t.string :name, :controller, :action, limit: 150
5
5
  t.timestamps
6
6
  end
7
7
 
8
8
  change_table :rights do |t|
9
9
  t.index :action
10
10
  t.index :name
11
- t.index [:controller, :action]
11
+ t.index %i[controller action]
12
12
  end
13
13
 
14
- create_table :rights_roles, :id => false do |t|
15
- t.integer :right_id, :role_id
14
+ create_table :rights_roles, id: false do |t|
15
+ t.integer %i[right_id role_id]
16
16
  end
17
17
 
18
18
  change_table :rights_roles do |t|
19
- t.index [:right_id, :role_id]
20
- t.index [:role_id, :right_id]
19
+ t.index %i[right_id role_id]
20
+ t.index %i[role_id right_id]
21
21
  end
22
22
 
23
23
  create_table :roles do |t|
@@ -4,5 +4,12 @@ module RightOn
4
4
  require 'rails'
5
5
  require 'right_on/railtie'
6
6
  require 'right_on/rights_manager'
7
- end
8
7
 
8
+ def self.rights_yaml(file_path = nil)
9
+ if file_path
10
+ @rights_yaml = file_path
11
+ else
12
+ @rights_yaml
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module RightOn
2
+ module Ability
3
+ include CanCan::Ability
4
+
5
+ private def add_rule_for(right)
6
+ add_rule(RightOn::Rule.rule_for(right))
7
+ end
8
+ end
9
+ end
@@ -1,23 +1,24 @@
1
1
  module RightOn
2
2
  class ByGroup
3
+ def self.rights
4
+ new.by_groups
5
+ end
6
+
3
7
  def initialize
4
8
  @rights_by_name = Hash[Right.all.map{|r| [r.name, r]}]
5
9
  end
6
10
 
7
11
  def by_groups
8
- rights = regular_rights_with_group
9
- rights += (Right.all - rights)
10
- rights.group_by(&:group)
12
+ yaml_rights.each_pair.with_object({}) do |(group, right_names), hash|
13
+ hash[group] = right_names
14
+ .flat_map { |right_name| right_name_to_rights(right_name) }
15
+ end
11
16
  end
12
17
 
13
18
  private
14
19
 
15
- def regular_rights_with_group
16
- RightOn::Right.yaml_rights.each_pair.flat_map do |group, right_names|
17
- right_names
18
- .flat_map { |right_name| right_name_to_rights(right_name) }
19
- .each { |r| r.group = group }
20
- end
20
+ def yaml_rights
21
+ YAML.load_file(RightOn.rights_yaml)['rights']
21
22
  end
22
23
 
23
24
  def right_name_to_rights(right_name)
@@ -41,7 +42,9 @@ module RightOn
41
42
  end
42
43
 
43
44
  def rights_by_name!(name)
44
- @rights_by_name[name] or fail name.inspect
45
+ @rights_by_name[name] or fail RightOn::RightNotFound, name.inspect
45
46
  end
46
47
  end
48
+
49
+ RightNotFound = Class.new(RightOn::Error)
47
50
  end
@@ -0,0 +1,52 @@
1
+ module RightOn
2
+ module ControllerAdditions
3
+ def self.included(base)
4
+ base.module_eval do
5
+ class_attribute :rights_from
6
+ class_attribute :permission_denied_layout
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def authorize_action!
13
+ controller = (self.rights_from || params[:controller]).to_s
14
+ action = params[:action].to_s
15
+
16
+ return if can_access_controller_action?(controller, action)
17
+
18
+ fail CanCan::AccessDenied, "You are not authorized to access this page."
19
+ end
20
+
21
+ def can_access_controller_action?(controller, action)
22
+ (can?(:access, controller) && !Right.where(ccr_subject: controller + '#' + action).exists?) ||
23
+ can?(:access, controller + '#' + action)
24
+ end
25
+
26
+ def access_granted?
27
+ can? :access, [params[:controller], params[:action]].join('#')
28
+ end
29
+
30
+ def rescue_access_denied(exception)
31
+ @permission_denied_response = RightOn::PermissionDeniedResponse.new(params, controller_action_options)
32
+
33
+ respond_to do |format|
34
+ format.html do
35
+ render status: :unauthorized,
36
+ template: 'permission_denied',
37
+ layout: ( permission_denied_layout || false )
38
+ end
39
+
40
+ format.json do
41
+ render status: :unauthorized, json: @permission_denied_response.to_json
42
+ end
43
+ end
44
+ end
45
+
46
+ def controller_action_options
47
+ opts = params.slice(:controller, :action)
48
+ opts[:controller] = rights_from.to_s if rights_from
49
+ opts
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module RightOn
2
+ class Error < StandardError; end
3
+ end
@@ -4,7 +4,8 @@ module RightOn
4
4
 
5
5
  def initialize(params, controller_action_options)
6
6
  @params = params
7
- @right_allowed = Right.all.detect{|right| right.allowed?(controller_action_options)}
7
+ allower = RightAllowed.new(controller_action_options[:controller], controller_action_options[:action])
8
+ @right_allowed = RightOn::Right.all.detect { |right| allower.allowed?(right) }
8
9
  @roles_allowed = @right_allowed.roles if @right_allowed
9
10
  @controller_name = @params[:controller] unless @right_allowed
10
11
  end
@@ -1,6 +1,11 @@
1
1
  require 'right_on/role_model'
2
+ require 'right_on/ability'
3
+ require 'right_on/rule'
4
+ require 'right_on/error'
2
5
  require 'right_on/right'
3
6
  require 'right_on/role'
7
+ require 'right_on/right_allowed'
4
8
  require 'right_on/by_group'
5
- require 'right_on/action_controller_extensions'
9
+ require 'cancan/exceptions'
10
+ require 'right_on/controller_additions'
6
11
  require 'right_on/permission_denied_response'
@@ -10,70 +10,8 @@ module RightOn
10
10
 
11
11
  scope :ordered, -> { order :name }
12
12
 
13
- after_save :clear_cache
14
- after_destroy :clear_cache
15
-
16
- attr_accessor :group
17
-
18
- class << self
19
- def rights_yaml(file_path)
20
- @@rights_yaml = file_path
21
- end
22
-
23
- def by_groups
24
- RightOn::ByGroup.new.by_groups
25
- end
26
-
27
- def yaml_rights
28
- YAML::load_file(@@rights_yaml)['rights']
29
- end
30
- end
31
-
32
- # Is this right allowed for the given context?
33
- #
34
- # Context params is an option hash:
35
- # :controller => controller name
36
- # :action => action name
37
- #
38
- # The context tells us the state of the request being made.
39
-
40
- def allowed?(context={})
41
- return false unless controller == context[:controller]
42
- if action
43
- action_permitted?(context[:action])
44
- else
45
- # right without action works if no specific right exists
46
- # e.g. can't edit if there's a edit or change right defined
47
- # as you must used that specific right
48
- specific_rights = Array(APPLICABLE_RIGHTS[context[:action].to_sym]) + [context[:action]]
49
- specific_rights.all?{|action| Right["#{context[:controller]}##{action}"].nil?}
50
- end
51
- end
52
-
53
- APPLICABLE_RIGHTS = {
54
- :new => [:change],
55
- :edit => [:change],
56
- :update => [:change],
57
- :create => [:change],
58
- :destroy => [:change],
59
- :index => [:change, :view],
60
- :show => [:change, :view]
61
- }
62
-
63
- CHANGE_ACTIONS = %w(new edit update create destroy index show)
64
-
65
- VIEW_ACTIONS = %w(index show)
66
-
67
- def action_permitted?(context_action)
68
- case action.to_sym
69
- when :change
70
- CHANGE_ACTIONS.include?(context_action)
71
- when :view
72
- VIEW_ACTIONS.include?(context_action)
73
- else
74
- action == context_action
75
- end
76
- end
13
+ after_save { RightOn::RightAllowed.clear_cache }
14
+ after_destroy { RightOn::RightAllowed.clear_cache }
77
15
 
78
16
  def sensible_name
79
17
  name.humanize.titleize.gsub(/#/, ' - ')
@@ -82,35 +20,5 @@ module RightOn
82
20
  def to_s
83
21
  name
84
22
  end
85
-
86
- def self.cache
87
- @@cache ||= Rails.cache
88
- end
89
-
90
- def self.cache=(cache)
91
- @@cache = cache
92
- end
93
-
94
- def self.clear_cache
95
- cache.delete('Right.all')
96
- end
97
-
98
- def clear_cache
99
- self.class.clear_cache
100
- end
101
-
102
- attr_accessor :rights
103
- def self.[](name)
104
- @rights = cache.read('Right.all') || calculate_and_write_cache
105
- @rights[name]
106
- end
107
-
108
- private
109
- def self.calculate_and_write_cache
110
- right_cache = Hash[Right.all.map{|r|[r.name, r.id]}]
111
- cache.write('Right.all', right_cache) or raise RuntimeError, "Could not cache rights"
112
- right_cache
113
- end
114
-
115
23
  end
116
24
  end
@@ -0,0 +1,71 @@
1
+ module RightOn
2
+ class RightAllowed
3
+ def initialize(controller, action)
4
+ @controller = controller
5
+ @action = action
6
+ end
7
+
8
+ def allowed?(right)
9
+ return false unless right.controller == @controller
10
+ if right.action
11
+ action_permitted?(right.action)
12
+ else
13
+ # right without action works if no specific right exists
14
+ # e.g. can't edit if there's a edit or change right defined
15
+ # as you must used that specific right
16
+ specific_rights = Array(APPLICABLE_RIGHTS[@action.to_sym]) + [@action]
17
+ specific_rights.all?{|action| self.class["#{@controller}##{action}"].nil?}
18
+ end
19
+ end
20
+
21
+ APPLICABLE_RIGHTS = {
22
+ :new => [:change],
23
+ :edit => [:change],
24
+ :update => [:change],
25
+ :create => [:change],
26
+ :destroy => [:change],
27
+ :index => [:change, :view],
28
+ :show => [:change, :view]
29
+ }
30
+
31
+ CHANGE_ACTIONS = %w(new edit update create destroy index show)
32
+
33
+ VIEW_ACTIONS = %w(index show)
34
+
35
+ def action_permitted?(action)
36
+ case action.to_sym
37
+ when :change
38
+ CHANGE_ACTIONS.include?(@action)
39
+ when :view
40
+ VIEW_ACTIONS.include?(@action)
41
+ else
42
+ action == @action
43
+ end
44
+ end
45
+
46
+ def self.cache
47
+ @@cache ||= Rails.cache
48
+ end
49
+
50
+ def self.cache=(cache)
51
+ @@cache = cache
52
+ end
53
+
54
+ def self.clear_cache
55
+ cache.delete('Right.all')
56
+ end
57
+
58
+ attr_accessor :rights
59
+ def self.[](name)
60
+ @rights = cache.read('Right.all') || calculate_and_write_cache
61
+ @rights[name]
62
+ end
63
+
64
+ private
65
+ def self.calculate_and_write_cache
66
+ right_cache = Hash[RightOn::Right.all.map{|r|[r.name, r.id]}]
67
+ cache.write('Right.all', right_cache) or raise RuntimeError, "Could not cache rights"
68
+ right_cache
69
+ end
70
+ end
71
+ end
@@ -1,16 +1,13 @@
1
1
  module RightOn
2
2
  module RoleModel
3
3
  def self.included(base)
4
- base.module_eval 'has_and_belongs_to_many :roles, :class_name => "RightOn::Role"'
5
- Role.module_eval "has_and_belongs_to_many :#{base.table_name}"
6
- end
7
-
8
- def rights
9
- @rights ||=
10
- Right
11
- .select('distinct rights.*')
12
- .joins(:roles)
13
- .where('rights_roles.role_id IN (?)', role_ids)
4
+ base.module_eval do
5
+ has_and_belongs_to_many :roles, class_name: 'RightOn::Role'
6
+ has_many :rights, through: :roles, class_name: 'RightOn::Right'
7
+ end
8
+ Role.module_eval do
9
+ has_and_belongs_to_many base.table_name.to_sym, dependent: :restrict
10
+ end
14
11
  end
15
12
 
16
13
  def has_privileges_of?(other_user)