can_field 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d3468acfaf9c73a05f5fcab6e9753ba27df93858
4
+ data.tar.gz: a42426ddc1769f28c467a114dbeb9f0e38787ac8
5
+ SHA512:
6
+ metadata.gz: 0da21c94dd1b608056d84ada848e53ec50cb8e4092750f663a8fa1e351c6430a333db75ab72d5bb1dce204366bc4ca2e074e6f154478372b07b59d42d2a5d28f
7
+ data.tar.gz: b152ffc10ba960210fd2ce8e833e63e981c83de16803fd9eb1df06cc729e283be98f0bc9325922aee98db177c3a83b0f77458177e723f4f710afd830b0091743
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## v0.0.1
2
+
3
+ * initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in can_field.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Roman Kolesnev
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # CanField
2
+
3
+ [CanCan](https://github.com/ryanb/cancan) provides only model-level permissions. This gem adds field-based permissions to CanCan using [strong_parameters gem](https://github.com/rails/strong_parameters).
4
+
5
+ **Warning!** Currently gem doesn't support any nested logic!
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'can_field'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install can_field
20
+
21
+ ## Usage
22
+
23
+ ### ability.rb
24
+
25
+ Now you have new method for you ability.rb file.
26
+
27
+ ```ruby
28
+ canf(actions, target, fields)
29
+
30
+ # example usage
31
+
32
+ canf :update, Book, [:title, :desription]
33
+ canf [:create, :update], Shelf, [:position]
34
+ ```
35
+
36
+ This method invoke standart `can` method with give `actions` and `targer` and generate some additional rules for restrict field access (`:_cf_action_fl_field` as example).
37
+
38
+ ### In controller
39
+
40
+ There is a contrller class method that provides integration with `load_and_authorize_resource`. Just add `permit_can_field_constraints` right after `load_and_authorize_resource` call. Like this:
41
+
42
+ ```ruby
43
+ class BooksController < ApplicationController
44
+ load_and_authorize_resource
45
+ permit_can_field_constraints
46
+
47
+ ...
48
+
49
+ end
50
+ ```
51
+
52
+ ### Helpers
53
+
54
+ In controller and views you can use helpers `canf?` and `allowed_fields_for`:
55
+
56
+ ```ruby
57
+ allowed_fields_for(action, subject) # return list of available fields or [:all] if no restrictions
58
+ allowed_fields_for :create, Book # as example
59
+
60
+ canf?(action, subject, field) # like can? but look for field restrictions
61
+ canf? :update, Book, :title # as example
62
+ ```
63
+
64
+ ## Contributing
65
+
66
+ 1. Fork it
67
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
68
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
69
+ 4. Push to the branch (`git push origin my-new-feature`)
70
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -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
data/can_field.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'can_field/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "can_field"
8
+ spec.version = CanField::VERSION
9
+ spec.authors = ["Roman Kolesnev"]
10
+ spec.email = ["rvkolesnev@gmail.com"]
11
+ spec.description = %q{CanCan constraints for fields using strong_parameters}
12
+ spec.summary = %q{This gem provide extension for CanCan and some new helpers for restrict access on field level.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'cancan'
22
+ spec.add_dependency 'strong_parameters'
23
+ spec.add_dependency 'rails', '< 4.0.0'
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "active_attr"
29
+ end
data/lib/can_field.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "can_field/version"
2
+ require "can_field/can_can/rule_additions"
3
+ require "can_field/can_can/ability_additions"
4
+ require "can_field/controller_additions"
5
+
6
+ module CanField
7
+ end
@@ -0,0 +1,36 @@
1
+ module CanField
2
+ module CanCan
3
+ module AbilityAdditions
4
+ # see README.md
5
+ def canf(actions, target, fields)
6
+ unless actions.is_a? Array
7
+ actions = [actions]
8
+ end
9
+
10
+ unless fields.is_a? Array
11
+ fields = [fields]
12
+ end
13
+
14
+ actions.each do |action|
15
+ can action.to_sym, target
16
+ end
17
+
18
+ actions.product(fields).each do |x|
19
+ action, field = x
20
+ can "_cf_#{action}_fl_#{field}".to_sym, target
21
+ end
22
+ end
23
+
24
+ # for internal use
25
+ def abilities_for_subject(subject)
26
+ @rules.select{|a| a.relevant_for_subject? subject}.map(&:actions).flatten.uniq
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ if defined? CanCan::Ability
33
+ CanCan::Ability.class_eval do
34
+ include CanField::CanCan::AbilityAdditions
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ module CanField
2
+ module CanCan
3
+
4
+ module RuleAdditions
5
+ # for internal use
6
+ def relevant_for_subject?(subject)
7
+ @match_all || matches_subject?(subject)
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+
14
+ if defined? CanCan::Rule
15
+ CanCan::Rule.class_eval do
16
+ include CanField::CanCan::RuleAdditions
17
+ end
18
+ end
@@ -0,0 +1,59 @@
1
+ module CanField
2
+ module ControllerAdditions
3
+ module ClassMethods
4
+ def permit_can_field_constraints
5
+ resource_name = self.to_s.sub("Controller", "").underscore.split('/').last.singularize
6
+ model = Kernel.const_get(resource_name.camelcase)
7
+
8
+ [:update, :create].each do |action|
9
+ prepend_before_filter(only: action) do
10
+ if params.has_key?(resource_name)
11
+ keys = allowed_fields_for action, model
12
+ if keys == [:all]
13
+ self.params[resource_name] = params[resource_name].permit!
14
+ else
15
+ self.params[resource_name] = params[resource_name].permit *keys
16
+ end
17
+ else
18
+ self.params = params.permit, *keys
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ module InstanceMethods
26
+ def allowed_fields_for(action, subject)
27
+ #TODO: gen cool rules
28
+ abilities = Ability.new(current_user).abilities_for_subject(subject).map(&:to_s).group_by{|x| x[0..2] == '_cf' ? :field : :mass}
29
+
30
+ re = /\A_cf_(?<action>\w+)_fl_(?<field>\w+)$/
31
+ result = (abilities[:field] || []).map do |a|
32
+ x = re.match(a)
33
+ [x[:action], x[:field]]
34
+ end.select{|a| a[0] == action.to_s}.map{|a| a[1]}.map(&:to_sym)
35
+
36
+ result << :all if result == []
37
+
38
+ result
39
+ end
40
+
41
+ def canf?(action, subject, field)
42
+ allowed_fields_for(action, subject).include?(field.to_sym) or
43
+ allowed_fields_for(action, subject).include?(:all)
44
+ end
45
+ end
46
+
47
+ def self.included(receiver)
48
+ receiver.extend ClassMethods
49
+ receiver.send :include, InstanceMethods
50
+ receiver.helper_method :allowed_fields_for, :canf?
51
+ end
52
+ end
53
+ end
54
+
55
+ if defined? ActionController::Base
56
+ ActionController::Base.class_eval do
57
+ include CanField::ControllerAdditions
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module CanField
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ class Book
4
+ include ActiveAttr::Model
5
+ end
6
+
7
+ class Shelf
8
+ include ActiveAttr::Model
9
+ end
10
+
11
+ class Ability
12
+ include CanCan::Ability
13
+
14
+ def initialize
15
+ canf :update, Book, :title
16
+
17
+ canf [:create, :update], Shelf, [:name, :position]
18
+ end
19
+ end
20
+
21
+ describe "CanField::CanCan" do
22
+ describe "::AbilityAdditions" do
23
+ subject{ ability }
24
+ let(:ability) {Ability.new}
25
+
26
+ describe "#canf" do
27
+ it { should be_able_to(:_cf_update_fl_title, Book.new) }
28
+ it { should_not be_able_to(:_cf_update_fl_author, Book.new) }
29
+
30
+ it { should be_able_to(:update, Book.new) }
31
+ it { should_not be_able_to(:create, Book.new) }
32
+
33
+ it { should be_able_to(:_cf_update_fl_name, Shelf.new) }
34
+ it { should be_able_to(:_cf_update_fl_position, Shelf.new) }
35
+ it { should be_able_to(:_cf_create_fl_name, Shelf.new) }
36
+ it { should be_able_to(:_cf_create_fl_position, Shelf.new) }
37
+
38
+ it { should be_able_to(:update, Shelf.new)}
39
+ it { should be_able_to(:create, Shelf.new)}
40
+ it { should_not be_able_to(:read, Shelf.new)}
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,4 @@
1
+ require "cancan"
2
+ require "can_field"
3
+ require "active_attr"
4
+ require "cancan/matchers"
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: can_field
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Roman Kolesnev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-03-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cancan
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: strong_parameters
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - <
46
+ - !ruby/object:Gem::Version
47
+ version: 4.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - <
53
+ - !ruby/object:Gem::Version
54
+ version: 4.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: active_attr
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: CanCan constraints for fields using strong_parameters
112
+ email:
113
+ - rvkolesnev@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - .rspec
120
+ - .travis.yml
121
+ - CHANGELOG.md
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - can_field.gemspec
127
+ - lib/can_field.rb
128
+ - lib/can_field/can_can/ability_additions.rb
129
+ - lib/can_field/can_can/rule_additions.rb
130
+ - lib/can_field/controller_additions.rb
131
+ - lib/can_field/version.rb
132
+ - spec/can_field/can_can_spec.rb
133
+ - spec/spec_helper.rb
134
+ homepage: ''
135
+ licenses:
136
+ - MIT
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 2.0.0
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: This gem provide extension for CanCan and some new helpers for restrict access
158
+ on field level.
159
+ test_files:
160
+ - spec/can_field/can_can_spec.rb
161
+ - spec/spec_helper.rb