cancando 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1a52f50f7d79f1e3211409f3df36adde0c6deef7
4
+ data.tar.gz: 63884bf162be00902add65c10cd3c4c8999e0b7b
5
+ SHA512:
6
+ metadata.gz: ab562bf17fccef7fbbc6c8ad3cacdc6e80722ba92ec03ba9af61cf17a002f90694b249705c7f9e94d6a948859484984de37bcb7afd6eb6aaa91ca7431b700979
7
+ data.tar.gz: 71c00b573218c6c9e996633b89d2af3342951ee93a4ccf15348a890c432d7e754ee9f507e3fc96aed6879839a10ac4b4697723028e063cbad41e3c1372c0a172
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ .idea
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.5.3
7
+ before_install: gem install bundler -v 2.0.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in cancando.gemspec
4
+ gemspec
@@ -0,0 +1,37 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cancando (1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ cancancan (2.0.0)
10
+ diff-lcs (1.3)
11
+ rake (12.3.3)
12
+ rspec (3.8.0)
13
+ rspec-core (~> 3.8.0)
14
+ rspec-expectations (~> 3.8.0)
15
+ rspec-mocks (~> 3.8.0)
16
+ rspec-core (3.8.2)
17
+ rspec-support (~> 3.8.0)
18
+ rspec-expectations (3.8.4)
19
+ diff-lcs (>= 1.2.0, < 2.0)
20
+ rspec-support (~> 3.8.0)
21
+ rspec-mocks (3.8.1)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.8.0)
24
+ rspec-support (3.8.2)
25
+
26
+ PLATFORMS
27
+ ruby
28
+
29
+ DEPENDENCIES
30
+ bundler (~> 2.0)
31
+ cancancan (~> 2.0)
32
+ cancando!
33
+ rake (~> 12.3)
34
+ rspec (~> 3.0)
35
+
36
+ BUNDLED WITH
37
+ 2.0.2
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 viktormarkov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,67 @@
1
+ # Cancando
2
+
3
+ Helper for [Cancancan](https://github.com/CanCanCommunity/cancancan) gem.
4
+
5
+ Increase `accessible_by` query performance via ability merging.
6
+
7
+ If your app have more than one ability declaration for one resource
8
+ ```ruby
9
+ can :index, User, id: [1, 2, 3]
10
+ can :index, User, id: [4, 5, 6]
11
+ ```
12
+ `User.accessible_by(ability, :index)` generates sql query like that:
13
+ ```sql
14
+ SELECT users.* FROM users WHERE (users.id IN (4, 5, 6)) OR (users.id IN (1, 2, 3))
15
+ ```
16
+
17
+ In case of big data that fact causes significant performance issue.
18
+
19
+ Cancando helps to avoid that situation by merging conditions:
20
+ ```ruby
21
+ can :index, User, id: [1, 2, 3, 4, 5, 6]
22
+ ```
23
+
24
+ ## Installation
25
+
26
+ Add this line to your application's Gemfile:
27
+
28
+ ```ruby
29
+ gem 'cancando'
30
+ ```
31
+
32
+ And then execute:
33
+
34
+ $ bundle
35
+
36
+ Or install it yourself as:
37
+
38
+ $ gem install cancando
39
+
40
+ ## Usage
41
+
42
+ Important. You have to install [Cancancan](https://github.com/CanCanCommunity/cancancan) gem first.
43
+
44
+ 1) Add `include Cancando`
45
+ 2) User `can_do` and `cannot_do` instead of `can` and `cannot` from cancancan
46
+ 3) Call `apply` for merge and save abilities
47
+
48
+ Simple example:
49
+ ```ruby
50
+ class Permission
51
+ include Cancando
52
+
53
+ def grant_permission
54
+ can_do :index, User, company_id: available_company_ids
55
+ can_do :update, Company, id: current_user.company_id
56
+ apply
57
+ end
58
+ end
59
+ ```
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/viktormarkov/cancando. This project is intended to be a safe, welcoming space for collaboration.
64
+
65
+ ## License
66
+
67
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'cancando/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'cancando'
7
+ spec.version = Cancando::VERSION
8
+ spec.authors = ['Viktor Markov']
9
+ spec.email = ['viktormarkov25@gmail.com']
10
+
11
+ spec.summary = 'Increase accessible_by query performance via ability merging'
12
+ spec.description = 'Helper for Cancancan. Increase accessible_by query performance via ability merging'
13
+ spec.homepage = 'https://github.com/viktormarkov/cancando'
14
+ spec.license = 'MIT'
15
+ spec.platform = Gem::Platform::RUBY
16
+
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = 'exe'
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ['lib']
23
+
24
+ spec.add_development_dependency 'bundler', '~> 2.0'
25
+ spec.add_development_dependency 'cancancan', '~> 2.0'
26
+ spec.add_development_dependency 'rake', '~> 12.3'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ end
@@ -0,0 +1,105 @@
1
+ require 'cancan'
2
+
3
+ module Cancando
4
+ include CanCan::Ability
5
+
6
+ def can_do(actions, resource, conditions = {})
7
+ add(abilities, actions, resource, conditions)
8
+ end
9
+
10
+ def cannot_do(actions, resource, conditions = {})
11
+ add(restrictions, actions, resource, conditions)
12
+ end
13
+
14
+ def abilities
15
+ @abilities ||= Hash.new { |hash, k| hash[k] = [] }
16
+ end
17
+
18
+ def restrictions
19
+ @restrictions ||= Hash.new { |hash, k| hash[k] = [] }
20
+ end
21
+
22
+ def apply
23
+ merge_and_grant(abilities, 'can') if abilities
24
+ merge_and_grant(restrictions, 'cannot') if restrictions
25
+ end
26
+
27
+ private
28
+
29
+ def add(target, actions, resource, conditions)
30
+ Array(actions).each do |action|
31
+ target[resource] << {action: action, conditions: conditions}
32
+ end
33
+ end
34
+
35
+ def merge_and_grant(abilities_to_merge, method)
36
+ abilities_to_merge.each do |resource, abilities|
37
+ merged_abilities = []
38
+ abilities.each do |ability|
39
+ merge_abilities(merged_abilities, ability)
40
+ end
41
+ grant_abilities(merged_abilities, resource, method)
42
+ end
43
+ end
44
+
45
+ def merge_abilities(abilities, ability_to_merge)
46
+ if abilities.empty?
47
+ abilities << ability_to_merge
48
+ return
49
+ end
50
+
51
+ merged = false
52
+ abilities.each do |ability|
53
+ if same_actions?(ability[:action], ability_to_merge[:action]) &&
54
+ same_single_condition_attr?(ability_to_merge[:conditions], ability[:conditions])
55
+
56
+ merge_conditions(ability, ability_to_merge)
57
+ merge_actions(ability, ability_to_merge)
58
+ merged = true
59
+ break
60
+ elsif equal_conditions?(ability_to_merge[:conditions], ability[:conditions])
61
+ merge_actions(ability, ability_to_merge)
62
+ merged = true
63
+ break
64
+ end
65
+ end
66
+
67
+ abilities << ability_to_merge unless merged
68
+ end
69
+
70
+ def same_actions?(actions1, actions2)
71
+ if actions1.is_a? Array
72
+ actions1.include? actions2
73
+ else
74
+ actions1 == actions2
75
+ end
76
+ end
77
+
78
+ def same_single_condition_attr?(conditions1, conditions2)
79
+ conditions1.length == 1 && conditions1.keys == conditions2.keys
80
+ end
81
+
82
+ def equal_conditions?(conditions1, conditions2)
83
+ conditions1.sort == conditions2.sort
84
+ end
85
+
86
+ def merge_conditions(ability1, ability2)
87
+ attr_value1 = ability1[:conditions].first[1]
88
+ attr_value2 = ability2[:conditions].first[1]
89
+ attr_name = ability2[:conditions].first[0]
90
+ merged_value = (Array(attr_value1) + Array(attr_value2)).uniq
91
+
92
+ ability1[:conditions][attr_name] = merged_value.length == 1 ? merged_value[0] : merged_value
93
+ end
94
+
95
+ def merge_actions(ability1, ability2)
96
+ ability1[:action] = (Array(ability1[:action]) + Array(ability2[:action])).uniq
97
+ end
98
+
99
+ # apply abilities by cancanan methods can or cannot
100
+ def grant_abilities(abilities, resource, method)
101
+ abilities.each do |ability|
102
+ send(method, ability[:action], resource, ability[:conditions])
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,3 @@
1
+ module Cancando
2
+ VERSION = "1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cancando
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Viktor Markov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-03-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: cancancan
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: Helper for Cancancan. Increase accessible_by query performance via ability
70
+ merging
71
+ email:
72
+ - viktormarkov25@gmail.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".idea/cancando.iml"
79
+ - ".idea/misc.xml"
80
+ - ".idea/modules.xml"
81
+ - ".idea/workspace.xml"
82
+ - ".rspec"
83
+ - ".travis.yml"
84
+ - Gemfile
85
+ - Gemfile.lock
86
+ - LICENSE.txt
87
+ - README.md
88
+ - Rakefile
89
+ - cancando.gemspec
90
+ - lib/cancando.rb
91
+ - lib/cancando/version.rb
92
+ homepage: https://github.com/viktormarkov/cancando
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.6.14
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Increase accessible_by query performance via ability merging
116
+ test_files: []