break_dance 0.4.0 → 0.9.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,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZDMyMDU1MTVkZDVkNjFjM2Q1MTAxM2I1ZDNlODUyNWRmNmNkMWU3ZA==
5
- data.tar.gz: !binary |-
6
- M2YyZmQ4N2JmZWQ1YWUyNGJmZmVjNWNjYzAxMDJmOTY5MDAzZWZmMw==
2
+ SHA1:
3
+ metadata.gz: 0d2eded9292f501fe9c7c4cd28220706c696a3bb
4
+ data.tar.gz: 9c818de083853d12006836607e5f0265b2a92875
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ODQzMjMxZjQ4OWNkOGM4NDc3N2M2NTQ1NmJlNjhhZjY0YTBlMjBjN2RlOTcx
10
- YjQ5YTI4ZTdhZDMxYzNlYjJhMzhjYmMwNTIxMzJjODFlZjYwMzEzNjdiNDQx
11
- YTk0Mjk4MjdlZTMyN2UxN2E1NWI5MTQ0MWRlZGI5MTYyOTdkODk=
12
- data.tar.gz: !binary |-
13
- ZGI2ZjZhMTJlY2ZhZGFjMWRjMzFmOWY4YzczZDFkYzRiOTRmOTM2Yjg2YjRi
14
- MDQ1MDBmYmU5Njg0MGUyZGM2ZDQ1ZWFjMzk5Njc2Njc3MThkZGVlNzc5Mzcx
15
- Y2ZhNzdkZDk3NWRlZDY5NTk5MGE3OGZiZjJmNzU0NzU1ZWU0M2I=
6
+ metadata.gz: 570bb6582af6055b94bfec493269f45ab06773f36ae98aa5e1bfbe57f02b3aa7a5ef9f60f2020fdc6c45361a5d2eb3173b55e7152d32d0bd154e5081b92e0b3d
7
+ data.tar.gz: 7e7264a95d88a99142cbc77f4405180ba2d9c96e3aa69ad46bc553a6b855e5343c3c8eeab945cba26c37044442d7de30c1c17ca7703426d0cc992344286fcd4d
@@ -1,6 +1,4 @@
1
- Copyright (c) 2014 Zlatko Zahariev
2
-
3
- MIT License
1
+ Copyright 2017 Zlatko Zahariev
4
2
 
5
3
  Permission is hereby granted, free of charge, to any person obtaining
6
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,29 +1,28 @@
1
1
  # BreakDance
2
+ Short description and motivation.
2
3
 
3
- TODO: Write a gem description
4
+ ## Usage
5
+ How to use my plugin.
4
6
 
5
7
  ## Installation
6
-
7
8
  Add this line to your application's Gemfile:
8
9
 
9
- gem 'break_dance'
10
+ ```ruby
11
+ gem 'break_dance'
12
+ ```
10
13
 
11
14
  And then execute:
12
-
13
- $ bundle
15
+ ```bash
16
+ $ bundle
17
+ ```
14
18
 
15
19
  Or install it yourself as:
16
-
17
- $ gem install break_dance
18
-
19
- ## Usage
20
-
21
- TODO: Write usage instructions here
20
+ ```bash
21
+ $ gem install break_dance
22
+ ```
22
23
 
23
24
  ## Contributing
25
+ Contribution directions go here.
24
26
 
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile CHANGED
@@ -1 +1,33 @@
1
- require "bundler/gem_tasks"
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'BreakDance'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+
33
+ task default: :test
data/lib/break_dance.rb CHANGED
@@ -1,14 +1,12 @@
1
- require 'request_store'
1
+ require 'request_store_rails'
2
2
 
3
3
  require 'break_dance/controller_additions'
4
4
  require 'break_dance/exceptions'
5
- require 'break_dance/security_policy_additions'
6
- require 'break_dance/security_policies_holder'
7
- require 'break_dance/security_scoping'
8
- require 'break_dance/version'
5
+ require 'break_dance/policy'
6
+ require 'break_dance/policy_additions'
7
+ require 'break_dance/application_record_additions'
9
8
 
10
- ActiveRecord::Base.send(:include, BreakDance::SecurityScoping)
9
+ require 'break_dance/version'
11
10
 
12
11
  module BreakDance
13
-
14
- end
12
+ end
@@ -0,0 +1,57 @@
1
+ module BreakDance
2
+ module ApplicationRecordAdditions
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ # We cannot use alias_method here, because "super" of the aliased method is the "super" of the original method.
7
+ %w(default_scoped unscoped).each do |method_name|
8
+ define_method method_name do |unsecured: false, &block|
9
+ if RequestLocals.store[:break_dance_enabled] && !unsecured
10
+ policy = RequestLocals.store[:break_dance_policy]
11
+
12
+ raise PolicyNotFound.new('BreakDance::Policy is not defined. By design BreakDance requires all models to be scoped.') unless policy.is_a?(BreakDance::Policy)
13
+ raise ModelWithoutScope.new("Model \"#{self.name}\" is missing BreakDance::Policy declaration. By design BreakDance requires all models to be scoped.") unless policy.scopes.has_key?(self.name)
14
+
15
+ super(&block).merge(policy.scopes[self.name])
16
+ else
17
+ super(&block)
18
+ end
19
+ end
20
+ end
21
+
22
+ def unsecured!(&block)
23
+ default_scoped(unsecured: true, &block)
24
+ end
25
+
26
+ def unsecured_unscoped!(&block)
27
+ unscoped(unsecured: true, &block)
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
34
+
35
+ # We monkey patch target_scope by just call .unsecured! on relation = ...
36
+ # This is necessary because otherwise some parts of the BreakDance scopes leaked from some joined models.
37
+ # The worse thing here is that this method excludes some parts of the scopes. So we can end up with leaked "where"
38
+ # with no "select" or "join".
39
+ # ToDo: However This may lead to unexpected behaviour if AR changes in future version, it is not tested for STI models and I generally don't like exactly this approach.
40
+ module ActiveRecord
41
+ module Associations
42
+ module ThroughAssociation
43
+
44
+ def target_scope
45
+ scope = super
46
+ reflection.chain.drop(1).each do |reflection|
47
+ relation = reflection.klass.unsecured!.all
48
+ scope.merge!(
49
+ relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
50
+ )
51
+ end
52
+ scope
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -2,8 +2,8 @@ module BreakDance
2
2
  module ControllerAdditions
3
3
  module ClassMethods
4
4
  def enable_authorization!
5
- before_filter :prepare_security_policy
6
- before_filter :access_filter
5
+ append_before_action :prepare_policy
6
+ append_before_action :access_filter
7
7
  end
8
8
  end
9
9
 
@@ -12,25 +12,21 @@ module BreakDance
12
12
  base.helper_method :can?, :cannot?
13
13
  end
14
14
 
15
- def with_authorization?
16
- @with_authorization || false
17
- end
18
-
19
15
  def can?(action, resource)
20
- return true unless with_authorization?
16
+ return true unless RequestLocals.store[:break_dance_enabled]
21
17
 
22
18
  allowed_permissions = current_permissions['resources'].select { |_,v| v == '1'}
23
19
 
24
20
  allowed = allowed_permissions.any? do |r|
25
- RequestStore.store[:security_policy_holder].resources[r[0].to_sym] and RequestStore.store[:security_policy_holder].resources[r[0].to_sym][:can].any? do |k,v|
21
+ RequestLocals.store[:break_dance_policy].resources[r[0].to_sym] and RequestLocals.store[:break_dance_policy].resources[r[0].to_sym][:can].any? do |k,v|
26
22
  v = Array.wrap(v)
27
23
  k == resource.to_sym && (
28
24
  (
29
25
  v.include?(:all_actions) &&
30
26
  !(
31
- RequestStore.store[:security_policy_holder].resources[r[0].to_sym][:except] &&
32
- RequestStore.store[:security_policy_holder].resources[r[0].to_sym][:except][resource.to_sym] &&
33
- RequestStore.store[:security_policy_holder].resources[r[0].to_sym][:except][resource.to_sym].include?(action.to_sym)
27
+ RequestLocals.store[:break_dance_policy].resources[r[0].to_sym][:except] &&
28
+ RequestLocals.store[:break_dance_policy].resources[r[0].to_sym][:except][resource.to_sym] &&
29
+ RequestLocals.store[:break_dance_policy].resources[r[0].to_sym][:except][resource.to_sym].include?(action.to_sym)
34
30
  )
35
31
  ) || v.include?(action.to_sym) )
36
32
  end
@@ -49,12 +45,9 @@ module BreakDance
49
45
 
50
46
  private
51
47
 
52
- def prepare_security_policy
53
- @with_authorization = true
54
-
55
- RequestStore.store[:security_policy_holder] = BreakDance::SecurityPoliciesHolder.new
56
-
48
+ def prepare_policy
57
49
  SecurityPolicy.new(current_user)
50
+ RequestLocals.store[:break_dance_enabled] = true
58
51
  end
59
52
 
60
53
  def access_filter
@@ -1,4 +1,10 @@
1
1
  module BreakDance
2
2
  class AccessDenied < StandardError
3
3
  end
4
+
5
+ class PolicyNotFound < StandardError
6
+ end
7
+
8
+ class ModelWithoutScope < StandardError
9
+ end
4
10
  end
@@ -0,0 +1,11 @@
1
+ module BreakDance
2
+ class Policy
3
+ attr_accessor :scopes, :resources, :excluded_select_values
4
+
5
+ def initialize
6
+ @scopes = {}
7
+ @resources = {}
8
+ @excluded_select_values = {}
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ module BreakDance
2
+ module PolicyAdditions
3
+ def scope(model)
4
+ RequestLocals.store[:break_dance_policy] ||= BreakDance::Policy.new
5
+
6
+ model_scope = RequestLocals.store[:break_dance_policy].scopes[model.name]
7
+
8
+ RequestLocals.store[:break_dance_policy].scopes[model.name] = model_scope.nil? ? yield(model.unscoped) : model_scope.merge(yield(model.unscoped))
9
+ end
10
+
11
+ def resource(key, resource)
12
+ RequestLocals.store[:break_dance_policy] ||= BreakDance::Policy.new
13
+
14
+ RequestLocals.store[:break_dance_policy].resources[key] = resource
15
+ end
16
+
17
+ # ToDo: Check & fix if we need to redefine also object.attributes or any other method to return us all attributes skipping direct attribute method call
18
+ # I.e. we now will receive 'nil' if a "column" is excluded, but we may access it via Object.find(x).attributes[:excluded_attribute]
19
+ def exclude_select_values(model, select_values)
20
+ RequestLocals.store[:break_dance_policy] ||= BreakDance::Policy.new
21
+
22
+ RequestLocals.store[:break_dance_policy].excluded_select_values[model.name] = select_values
23
+
24
+ select_values.each do |sv|
25
+ model.redefine_method sv do
26
+ if RequestLocals.store[:break_dance_policy]&.excluded_select_values[model.name]&.include? sv
27
+ nil
28
+ else
29
+ super()
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,3 @@
1
1
  module BreakDance
2
- VERSION = "0.4.0"
3
- end
2
+ VERSION = '0.9.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :break_dance do
3
+ # # Task goes here
4
+ # end
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: break_dance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zlatko Zahariev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-15 00:00:00.000000000 Z
11
+ date: 2017-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: request_store
14
+ name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: 5.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.0'
26
+ version: 5.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: request_store_rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.3'
34
- type: :development
33
+ version: '0'
34
+ type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.3'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: sqlite3
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  description: Rails authorization gem.
@@ -59,19 +59,17 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - .gitignore
63
- - Gemfile
64
- - LICENSE.txt
62
+ - MIT-LICENSE
65
63
  - README.md
66
64
  - Rakefile
67
- - break_dance.gemspec
68
65
  - lib/break_dance.rb
66
+ - lib/break_dance/application_record_additions.rb
69
67
  - lib/break_dance/controller_additions.rb
70
68
  - lib/break_dance/exceptions.rb
71
- - lib/break_dance/security_policies_holder.rb
72
- - lib/break_dance/security_policy_additions.rb
73
- - lib/break_dance/security_scoping.rb
69
+ - lib/break_dance/policy.rb
70
+ - lib/break_dance/policy_additions.rb
74
71
  - lib/break_dance/version.rb
72
+ - lib/tasks/break_dance_tasks.rake
75
73
  homepage: https://github.com/notentered/breakdance
76
74
  licenses:
77
75
  - MIT
@@ -82,17 +80,17 @@ require_paths:
82
80
  - lib
83
81
  required_ruby_version: !ruby/object:Gem::Requirement
84
82
  requirements:
85
- - - ! '>='
83
+ - - ">="
86
84
  - !ruby/object:Gem::Version
87
85
  version: '0'
88
86
  required_rubygems_version: !ruby/object:Gem::Requirement
89
87
  requirements:
90
- - - ! '>='
88
+ - - ">="
91
89
  - !ruby/object:Gem::Version
92
90
  version: '0'
93
91
  requirements: []
94
92
  rubyforge_project:
95
- rubygems_version: 2.2.2
93
+ rubygems_version: 2.6.12
96
94
  signing_key:
97
95
  specification_version: 4
98
96
  summary: Rails authorization for data-centric applications based on ActiveRecord.
data/.gitignore DELETED
@@ -1,20 +0,0 @@
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
18
- .idea
19
- .ruby-version
20
- .ruby-gemset
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in break_dance.gemspec
4
- gemspec
data/break_dance.gemspec DELETED
@@ -1,25 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'break_dance/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "break_dance"
8
- spec.version = BreakDance::VERSION
9
- spec.authors = ['Zlatko Zahariev']
10
- spec.email = ['zlatko.zahariev@gmail.com']
11
- spec.description = %q{Rails authorization gem.}
12
- spec.summary = %q{Rails authorization for data-centric applications based on ActiveRecord.}
13
- spec.homepage = 'https://github.com/notentered/breakdance'
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 "request_store", "~> 1.0"
22
-
23
- spec.add_development_dependency "bundler", "~> 1.3"
24
- spec.add_development_dependency "rake"
25
- end
@@ -1,10 +0,0 @@
1
- module BreakDance
2
- class SecurityPoliciesHolder < BasicObject
3
- attr_accessor :policies, :resources, :suppress_security_for
4
-
5
- def initialize
6
- @policies = {}
7
- @resources = {}
8
- end
9
- end
10
- end
@@ -1,19 +0,0 @@
1
- module BreakDance
2
- module SecurityPolicyAdditions
3
- def policy(name)
4
- @policy_name = name
5
- yield
6
- end
7
-
8
- def scope(model)
9
- model_name = model.name
10
- if @user and @user.permissions and @user.permissions['models'] and @user.permissions['models'].has_key? model_name and @user.permissions['models'][model_name] == @policy_name
11
- RequestStore.store[:security_policy_holder].policies[model.name] = yield(model.unscoped)
12
- end
13
- end
14
-
15
- def resource(key, resource)
16
- RequestStore.store[:security_policy_holder].resources[key] = resource
17
- end
18
- end
19
- end
@@ -1,33 +0,0 @@
1
- module BreakDance
2
- module SecurityScoping
3
- extend ActiveSupport::Concern
4
-
5
- module ClassMethods
6
- def where(scope = nil, *options)
7
- scope = super(scope, *options)
8
- return ActiveRecord::Relation.new(self, Arel::Table.new(table_name)) unless scope
9
-
10
- sph = RequestStore.store[:security_policy_holder]
11
- if sph
12
- if sph.suppress_security_for == self.name
13
- sph.suppress_security_for = nil
14
- scope
15
- else
16
- scope.merge(sph.policies[self.name]).readonly(false)
17
- end
18
- else
19
- scope
20
- end
21
- end
22
-
23
- def unsecured
24
- if RequestStore.store[:security_policy_holder]
25
- RequestStore.store[:security_policy_holder].suppress_security_for = self.name
26
- where
27
- else
28
- self
29
- end
30
- end
31
- end
32
- end
33
- end