break_dance 0.4.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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