critic 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d45e116551e704334c5a3c1ddd1d021edbc19fc6
4
+ data.tar.gz: a881f09af89ed7e572cd3d89724d13b6b62ef180
5
+ SHA512:
6
+ metadata.gz: 9df1a366cdae643e0ff01bc896146257c94335a4893e29ff7a30ab922b6e486c20be280de5b1e0d5718bcf4a6bfb43ce29140cc4fd6096e31a1935151ffc23f5
7
+ data.tar.gz: 9be579f0737285e880be3e5ca4976c3ecca7f7deaeb8ef1ff99e4b7b26796e1fceb29bf2ec4402e3966c051007291d32ec45d313e1e2b2bf5a7dfebec1ea9c38
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ spec/examples.txt
11
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,34 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+ DisplayCopNames: true
4
+ Exclude:
5
+ - 'spec/**/*'
6
+ Metrics/LineLength:
7
+ Max: 120
8
+ Style/BlockDelimiters:
9
+ EnforcedStyle: semantic
10
+ Style/BracesAroundHashParameters:
11
+ EnforcedStyle: context_dependent
12
+ Style/TrailingCommaInLiteral:
13
+ EnforcedStyleForMultiline: consistent_comma
14
+ Style/ClassAndModuleChildren:
15
+ EnforcedStyle: compact
16
+ Metrics/AbcSize:
17
+ Max: 75
18
+ Metrics/MethodLength:
19
+ Max: 50
20
+ Metrics/ClassLength:
21
+ Max: 300
22
+ Metrics/ModuleLength:
23
+ Max: 300
24
+ Metrics/CyclomaticComplexity:
25
+ Max: 10
26
+ Metrics/PerceivedComplexity:
27
+ Max: 10
28
+ Style/TrailingCommaInArguments:
29
+ Enabled: false
30
+ #EnforcedStyleForMultiline: consistent_comma # this is very broke
31
+ Style/StructInheritance:
32
+ Enabled: false
33
+ Style/AccessorMethodName:
34
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ sudo: false
3
+ cache:
4
+ - bundler
5
+ rvm:
6
+ - 2.3.0
7
+ - 2.2.4
8
+ - 2.1.8
9
+ script:
10
+ - bundle exec rubocop -D
11
+ - bundle exec rake spec
12
+ notifications:
13
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ source 'https://rubygems.org'
3
+
4
+ # Specify your gem's dependencies in critic.gemspec
5
+ gemspec
6
+
7
+ gem 'activesupport', '~> 3.2.22', require: false
8
+ gem 'rubocop', '~> 0.40', require: false
9
+
10
+ group :test do
11
+ gem 'pry-nav'
12
+ end
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # Critic
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/critic`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'critic'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install critic
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/critic.
36
+
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'critic'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/critic.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'critic/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'critic'
9
+ spec.version = Critic::VERSION
10
+ spec.authors = ['Josh Lane']
11
+ spec.email = ['me@joshualane.com']
12
+
13
+ spec.summary = 'Resource authorization'
14
+ spec.description = 'Resource authorization via PORO'
15
+ spec.homepage = 'http://lanej.io/critic'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'bin'
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.10'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'rspec'
25
+
26
+ spec.add_dependency 'activesupport', '> 3.0', '< 5.0'
27
+ end
data/lib/critic.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ require 'critic/version'
3
+ require 'active_support/concern'
4
+ require 'active_support/callbacks'
5
+ require 'active_support/version'
6
+ require 'active_support/core_ext/string/inflections'
7
+
8
+ # Namespace
9
+ module Critic; end
10
+
11
+ Critic::AuthorizationDenied = Class.new(StandardError)
12
+ Critic::AuthorizationMissing = Class.new(StandardError)
13
+
14
+ require 'critic/policy'
15
+ require 'critic/authorization'
16
+ require 'critic/controller'
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ class Critic::Authorization
3
+ attr_reader :policy, :action
4
+ attr_accessor :messages, :granted, :result
5
+
6
+ def initialize(policy, action)
7
+ @policy = policy
8
+ @action = action
9
+
10
+ @granted, @result = nil
11
+ @messages = []
12
+ end
13
+
14
+ def granted?
15
+ true == @granted
16
+ end
17
+
18
+ def denied?
19
+ false == @granted
20
+ end
21
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+ module Critic::Controller
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ if respond_to?(:hide_action)
7
+ hide_action(:authorize)
8
+ hide_action(:authorize_scope)
9
+ end
10
+ end
11
+
12
+ def authorize(resource, action=default_action, policy: policy(resource), with: nil)
13
+ authorizing!
14
+
15
+ args = [with] if !with.is_a?(Array) && !with.nil?
16
+
17
+ @authorization = policy.authorize(action, critic, resource, args)
18
+
19
+ authorization_failed! if @authorization.denied?
20
+
21
+ @authorization.result
22
+ end
23
+
24
+ def authorized?(resource, *args, **options)
25
+ authorize(resource, *args, **options)
26
+ rescue Critic::AuthorizationDenied
27
+ false
28
+ end
29
+
30
+ def authorize_scope(scope, *args, action: nil, policy: policy(scope))
31
+ authorization_action = action || policy.scope
32
+
33
+ authorize(scope, authorization_action, *args, policy: policy)
34
+ end
35
+
36
+ protected
37
+
38
+ attr_reader :authorization
39
+
40
+ def authorization_failed!
41
+ raise Critic::AuthorizationDenied, authorization.messages
42
+ end
43
+
44
+ def authorization_missing!
45
+ raise Critic::AuthorizationMissing
46
+ end
47
+
48
+ def verify_authorized
49
+ unless true == @_authorizing
50
+ authorization_missing!
51
+ else
52
+ true
53
+ end
54
+ end
55
+
56
+ def authorizing!
57
+ @_authorizing = true
58
+ end
59
+
60
+ def policy(object)
61
+ Critic::Policy.for(object)
62
+ end
63
+
64
+ def critic
65
+ (defined?(consumer) && consumer) || current_user
66
+ end
67
+
68
+ private
69
+
70
+ def default_action
71
+ defined?(params) && params[:action]
72
+ end
73
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+ module Critic::Policy
3
+ extend ActiveSupport::Concern
4
+
5
+ def self.policies
6
+ @_policies ||= Hash.new { |h, k| h[k.to_s] = nil }
7
+ end
8
+
9
+ # @fixme do we really wish to demodulize ?
10
+ def self.resource_class_for(object)
11
+ if object.respond_to?(:model_name)
12
+ # used for pulling class out of ActiveRecord::Relation objects
13
+ object.model_name
14
+ elsif object.is_a?(Class)
15
+ object.to_s.demodulize
16
+ else
17
+ object.class.to_s.demodulize
18
+ end
19
+ end
20
+
21
+ def self.for(resource)
22
+ resource_class = resource_class_for(resource)
23
+
24
+ policies.fetch(resource_class) { "#{resource_class}Policy".constantize }
25
+ end
26
+
27
+ included do
28
+ include ActiveSupport::Callbacks
29
+
30
+ if ActiveSupport::VERSION::MAJOR < 4
31
+ define_callbacks :authorize, terminator: 'authorization.result == false || result == false'
32
+ else
33
+ define_callbacks :authorize, terminator: ->(target, result) { target.authorization.result == false || false == result }
34
+ end
35
+ end
36
+
37
+ # Policy entry points
38
+ module ClassMethods
39
+ def authorize(action, subject, resource, args=nil)
40
+ new(subject, resource).authorize(action, *args)
41
+ end
42
+
43
+ def scope(action = nil)
44
+ action.nil? ? (@scope || :index) : (@scope = action)
45
+ end
46
+
47
+ def before_authorize(*args, **options, &block)
48
+ set_callback(:authorize, :before, *args, **options, &block)
49
+ end
50
+
51
+ def after_authorize(*args, **options, &block)
52
+ set_callback(:authorize, :after, *args, **options, &block)
53
+ end
54
+
55
+ def around_authorize(*args, **options, &block)
56
+ set_callback(:authorize, :around, *args, **options, &block)
57
+ end
58
+ end
59
+
60
+ attr_reader :subject, :resource, :errors
61
+ attr_accessor :authorization
62
+
63
+ def initialize(subject, resource)
64
+ @subject = subject
65
+ @resource = resource
66
+ @errors = []
67
+ end
68
+
69
+ def failure_message(action)
70
+ "#{subject} is not authorized to #{action} #{resource}"
71
+ end
72
+
73
+ def authorize(action, *args)
74
+ self.authorization = Critic::Authorization.new(self, action)
75
+
76
+ result = false
77
+
78
+ begin
79
+ run_callbacks(:authorize) { result = public_send(action, *args) }
80
+ rescue Critic::AuthorizationDenied
81
+ authorization.granted = false
82
+ ensure
83
+ authorization.result = result if authorization.result.nil?
84
+ end
85
+
86
+ case authorization.result
87
+ when Critic::Authorization
88
+ # user has accessed authorization directly
89
+ when String
90
+ authorization.granted = false
91
+ authorization.messages << result
92
+ when nil, false
93
+ authorization.granted = false
94
+ authorization.messages << failure_message(action)
95
+ else
96
+ authorization.granted = true
97
+ end
98
+
99
+ authorization
100
+ end
101
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module Critic
3
+ VERSION = '0.1.1'
4
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: critic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Josh Lane
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-07 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: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '5.0'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">"
70
+ - !ruby/object:Gem::Version
71
+ version: '3.0'
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '5.0'
75
+ description: Resource authorization via PORO
76
+ email:
77
+ - me@joshualane.com
78
+ executables:
79
+ - console
80
+ - setup
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - ".gitignore"
85
+ - ".rspec"
86
+ - ".rubocop.yml"
87
+ - ".travis.yml"
88
+ - Gemfile
89
+ - README.md
90
+ - Rakefile
91
+ - bin/console
92
+ - bin/setup
93
+ - critic.gemspec
94
+ - lib/critic.rb
95
+ - lib/critic/authorization.rb
96
+ - lib/critic/controller.rb
97
+ - lib/critic/policy.rb
98
+ - lib/critic/version.rb
99
+ homepage: http://lanej.io/critic
100
+ licenses: []
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.5.1
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Resource authorization
122
+ test_files: []