sand 0.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: 3e35fa0c449b867bf7a2a4ca9896bcef5dab595c
4
+ data.tar.gz: 97ae09fb52cb0a5e79f3a026682a8ee136dc7a47
5
+ SHA512:
6
+ metadata.gz: e207da09669c379140f79f5b976f61f9a19479ea4b883112beaa0853588f7fc4da5f543febee4c7b6fb68b532d49b17a077cdf980ea103f063ad3a37c077e58a
7
+ data.tar.gz: 81a1995877fdeb8491961fde669fde5ad89a29cdb16c2d000ef0d02ed6754ffd1d96ee8b6449fe30493a6b2f892efa95c12bb34f96bddf96e5ce3b4c9d67c954
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ README.md
3
+ ChangeLog.md
4
+
5
+ LICENSE.txt
@@ -0,0 +1,6 @@
1
+ /.bundle
2
+ /Gemfile.lock
3
+ /html/
4
+ /pkg/
5
+ /vendor/cache/*.gem
6
+ tags
@@ -0,0 +1,16 @@
1
+ --- !ruby/object:RDoc::Options
2
+ encoding: UTF-8
3
+ static_path: []
4
+ rdoc_include:
5
+ - .
6
+ charset: UTF-8
7
+ exclude:
8
+ hyperlink_all: false
9
+ line_numbers: false
10
+ main_page: README.md
11
+ markup: markdown
12
+ show_hash: false
13
+ tab_width: 8
14
+ title: sand Documentation
15
+ visibility: :protected
16
+ webcvs:
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
@@ -0,0 +1,6 @@
1
+ ---
2
+ Style/Documentation:
3
+ Enabled: false
4
+ AllCops:
5
+ Exclude:
6
+ - 'spec/support/*_app.rb'
@@ -0,0 +1,8 @@
1
+ ---
2
+ language: ruby
3
+ rvm:
4
+ - 2.0
5
+ - 2.1
6
+ - 2.2
7
+ before_install:
8
+ - gem install bundler
@@ -0,0 +1,4 @@
1
+ ### 0.1.0 / 2016-02-05
2
+
3
+ * Initial release:
4
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ Rack Specific modifications Copyright (c) 2016 Nick Tomlin
2
+ Otherwise Copyright (c) 2012 Jonas Nicklas, Elabs AB
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,50 @@
1
+ sand [![Build Status](https://travis-ci.org/NickTomlin/ruby-sand.svg?branch=master)](https://travis-ci.org/NickTomlin/ruby-sand)
2
+ ===
3
+
4
+ A ruby gem for authorization in rack/sinatra applications. Code mostly stolen from [Pundit](https://github.com/elabs/pundit).
5
+
6
+ Usage
7
+ ---
8
+
9
+ The [Pundit policy](https://github.com/elabs/pundit#policies) documentation provides an excellent introduction into creating defining policies.
10
+
11
+ Once you've built your policies, you can start to use sand. By default, you can include sand in your rack application like so:
12
+
13
+ ```ruby
14
+ require 'sand'
15
+ use Sand::Middleware
16
+
17
+ class MyModel < MyOrm::Model
18
+ # ...
19
+ end
20
+
21
+ class MyModelPolicy
22
+ # ...
23
+ end
24
+
25
+ class Routes
26
+ env['sand'].authorize(user, MyModel, :can_greet?)
27
+ [200, {}, ['Hello world']]
28
+ end
29
+
30
+ MyRackApp = Rack::Builder.new do
31
+ use Sand::Middleware
32
+ run SandApp.new
33
+ end
34
+ ```
35
+
36
+ This will add `authorize` and `policy_scope` underneath env['sand'], that you can call in your middleware / routes.
37
+
38
+ Sinatra users can access sand's middleware via helpers by adding `Sand::Helpers`:
39
+
40
+ ```ruby
41
+ require 'sinatra'
42
+
43
+ use Sand::Helpers
44
+
45
+ get '/' do
46
+ user = User.find(params[:user_id])
47
+ accounts = policy_scope(user, Account)
48
+ json accounts: accounts
49
+ end
50
+ ```
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'bundler/setup'
7
+ rescue LoadError => e
8
+ abort e.message
9
+ end
10
+
11
+ require 'rake'
12
+
13
+ require 'rubygems/tasks'
14
+ Gem::Tasks.new
15
+
16
+ require 'rdoc/task'
17
+ RDoc::Task.new
18
+ task doc: :rdoc
19
+
20
+ require 'rspec/core/rake_task'
21
+ RSpec::Core::RakeTask.new
22
+
23
+ require 'rubocop/rake_task'
24
+ RuboCop::RakeTask.new
25
+
26
+ task default: %w(rubocop spec)
@@ -0,0 +1,44 @@
1
+ require 'sand/version'
2
+ require 'sand/policy_finder'
3
+ require 'sand/util'
4
+ require 'sand/helpers'
5
+ require 'sand/middleware'
6
+
7
+ module Sand
8
+ class Error < StandardError; end
9
+ class NotDefinedError < Error; end
10
+ class AuthorizationNotPerformed < Error; end
11
+ class ScopeNotPerformed < Error; end
12
+
13
+ class NotAuthorizedError < Error
14
+ attr_reader :record, :query, :policy
15
+
16
+ def initialize(options)
17
+ @record = options[:record]
18
+ @query = options[:query]
19
+ @policy = options[:policy]
20
+
21
+ super("not allowed to #{query} this #{record.inspect}")
22
+ end
23
+ end
24
+
25
+ def self.authorize(user, record, query)
26
+ policy = policy!(user, record)
27
+
28
+ unless policy.public_send(query)
29
+ raise NotAuthorizedError.new(policy: policy, record: record, query: query) # rubocop:disable Style/RaiseArgs, Metrics/LineLength
30
+ end
31
+
32
+ true
33
+ end
34
+
35
+ def self.policy!(user, record)
36
+ policy = PolicyFinder.new(record).policy!
37
+ policy.new(user, record)
38
+ end
39
+
40
+ def self.policy_scope(user, scope)
41
+ policy_scope = PolicyFinder.new(scope).scope!
42
+ policy_scope.new(user, scope).resolve
43
+ end
44
+ end
@@ -0,0 +1,35 @@
1
+ module Sand
2
+ module Helpers
3
+ def policy_scope(user, record)
4
+ scoped!
5
+ scope = PolicyFinder.new(record).scope!
6
+ scope.new(user, record).resolve if scope
7
+ end
8
+
9
+ def authorize(user, record, query)
10
+ authorized!
11
+ policy = Sand.policy!(user, record)
12
+ unless policy.public_send(query)
13
+ raise Sand::NotAuthorizedError.new(policy: policy, query: query, record: record) # rubocop:disable Metrics/LineLength, Style/RaiseArgs
14
+ end
15
+ end
16
+
17
+ def skip_sand_authorization
18
+ authorized!
19
+ end
20
+
21
+ def skip_sand_scoping
22
+ scoped!
23
+ end
24
+
25
+ private
26
+
27
+ def authorized!
28
+ env['sand.authorized'] = true
29
+ end
30
+
31
+ def scoped!
32
+ env['sand.scoped'] = true
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,40 @@
1
+ module Sand
2
+ class RequestMethods
3
+ attr_accessor :env
4
+ include Sand::Helpers
5
+
6
+ def initialize(env)
7
+ @env = env
8
+ end
9
+ end
10
+
11
+ class Middleware
12
+ attr_reader :app, :env, :options, :response
13
+
14
+ DEFAULT_OPTIONS = {
15
+ pass: []
16
+ }.freeze
17
+
18
+ def initialize(app, options = {})
19
+ @env = nil
20
+ @app = app
21
+ @options = DEFAULT_OPTIONS.merge(options)
22
+ end
23
+
24
+ def passed?
25
+ return true if options[:pass].any? { |r| r =~ env['REQUEST_PATH'] }
26
+ return true if env['sand.pass'] == true || env['sand.scoped'] || env['sand.authorized'] == true # rubocop:disable Metrics/LineLength
27
+ false
28
+ end
29
+
30
+ def call(env)
31
+ @env = env
32
+ env['sand'] = RequestMethods.new(env)
33
+
34
+ result = app.call(env)
35
+
36
+ return result if passed?
37
+ raise Sand::AuthorizationNotPerformed
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,48 @@
1
+ module Sand
2
+ class PolicyFinder
3
+ POLICY_SUFFIX = 'Policy'.freeze
4
+
5
+ def initialize(object)
6
+ @object = object
7
+ end
8
+
9
+ def scope!
10
+ policy!::Scope
11
+ rescue NameError
12
+ raise NotDefinedError
13
+ end
14
+
15
+ def policy!
16
+ klass = find
17
+ klass = Util.constantize(klass) if klass.is_a?(String)
18
+ klass
19
+ rescue NameError
20
+ raise NotDefinedError
21
+ end
22
+
23
+ private
24
+
25
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/AbcSize, Metrics/LineLength
26
+ def find
27
+ klass = @object
28
+ return klass if @object.nil?
29
+
30
+ if @object.respond_to?(:sand_policy)
31
+ @object.sand_policy
32
+ elsif @object.class.respond_to?(:sand_policy)
33
+ @object.sand_policy
34
+ else
35
+ klass = if @object.is_a?(Symbol)
36
+ @object.to_s.camelize
37
+ elsif @object.respond_to?(:model)
38
+ @object.model
39
+ elsif @object.respond_to?(:model_class)
40
+ @object.model_class
41
+ else
42
+ @object.to_s
43
+ end
44
+ "#{klass}#{POLICY_SUFFIX}"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ module Sand
2
+ module Util
3
+ def self.constantize(str = '')
4
+ str.split('::').inject(Module) { |a, e| a.const_get(e) }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Sand
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'sand/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'sand'
9
+ gem.version = Sand::VERSION
10
+ gem.summary = 'Authorization for rack-based applications'
11
+ gem.description = 'A ruby gem for authorization for use in sinatra/rack applications. Heavily inspired [Pundit](https://github.com/elabs/pundit)' # rubocop:disable Metrics/LineLength
12
+ gem.license = 'MIT'
13
+ gem.authors = ['Nick Tomlin']
14
+ gem.email = 'nick.tomlin@gmail.com'
15
+ gem.homepage = 'https://rubygems.org/gems/sand'
16
+
17
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
18
+
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ['lib']
21
+
22
+ gem.add_development_dependency 'bundler', '~> 1.10'
23
+ gem.add_development_dependency 'rake', '~> 10.0'
24
+ gem.add_development_dependency 'rdoc', '~> 4.0'
25
+ gem.add_development_dependency 'rspec', '~> 3.0'
26
+ gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
27
+ gem.add_development_dependency 'rubocop', '~> 0.37.0'
28
+ gem.add_development_dependency 'pry', '0.10.3'
29
+ gem.add_development_dependency 'rack-test', '~> 0.6.3'
30
+ gem.add_development_dependency 'sinatra', '~> 1.4.7'
31
+ gem.add_development_dependency 'sequel', '~> 4.31'
32
+ gem.add_development_dependency 'sqlite3'
33
+ end
@@ -0,0 +1,2 @@
1
+ Metrics/LineLength:
2
+ Enabled: false # I'm fine with long specs :screaming-cat-face:
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+ require 'support/rack_app'
3
+ require 'rack/test'
4
+
5
+ RSpec.describe 'Sand in the context of a rack Application' do
6
+ include_examples 'RackApplications'
7
+
8
+ def app
9
+ MyRackApp
10
+ end
11
+ end
@@ -0,0 +1,72 @@
1
+ RSpec.shared_examples 'RackApplications' do
2
+ include Rack::Test::Methods
3
+
4
+ before(:each) do
5
+ # poor man's database cleaner
6
+ User.all.each(&:delete)
7
+ Account.all.each(&:delete)
8
+ end
9
+
10
+ let!(:user) { User.create(name: 'Normal User', admin: false) }
11
+ let!(:admin_user) { User.create(name: 'Admin User', admin: true) }
12
+
13
+ describe 'finding resources via policy_scope' do
14
+ it "returns resources based on the Policy's Scope.resolve for 'admin' users" do
15
+ 3.times { |x| Account.create(title: "Account #{x}") }
16
+ get "/users/#{admin_user.id}/accounts"
17
+
18
+ expect(last_response).to be_ok
19
+ body = JSON.parse(last_response.body)
20
+ expect(body.size).to eq(3)
21
+ end
22
+
23
+ it "returns resources based on the Policy's Scope.resolve for 'normal'" do
24
+ 2.times do |x|
25
+ account = Account.create(title: "Owned Account #{x}")
26
+ Role.create(role: 'Normal', user_id: user.id, account_id: account.id)
27
+ end
28
+
29
+ Account.create(title: 'Not owned Account')
30
+
31
+ get "/users/#{user.id}/accounts"
32
+
33
+ expect(last_response).to be_ok
34
+ body = JSON.parse(last_response.body)
35
+ expect(body.size).to eq(2)
36
+ end
37
+ end
38
+
39
+ describe 'verify_scoped' do
40
+ it 'raises a Sand::NotAuthorizedError if policy has not been authorized' do
41
+ expect do
42
+ get '/verify_scoped/fail'
43
+ end.to raise_error Sand::AuthorizationNotPerformed
44
+ end
45
+
46
+ it 'does nothing if resource has been authorized' do
47
+ get '/verify_scoped/succeed'
48
+
49
+ expect(last_response).to be_ok
50
+ end
51
+
52
+ it 'allows users to skip authorization' do
53
+ get '/verify_scoped/pass'
54
+
55
+ expect(last_response).to be_ok
56
+ end
57
+ end
58
+
59
+ describe 'verify_authorized' do
60
+ before { Account.create(title: 'Test') }
61
+ it 'raises an error if resource has not been authorized' do
62
+ expect do
63
+ get '/verify_authorized/fail'
64
+ end.to raise_error Sand::NotAuthorizedError
65
+ end
66
+
67
+ it 'does nothing if resource has been authorized' do
68
+ get '/verify_authorized/success'
69
+ expect(last_response).to be_ok
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ require 'support/sinatra_app'
3
+ require 'rack/test'
4
+ require 'json'
5
+
6
+ RSpec.describe Sand::Helpers do
7
+ include_examples 'RackApplications'
8
+
9
+ def app
10
+ Sinatra::Application
11
+ end
12
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Sand do
4
+ class PostPolicy < Struct.new(:user, :post) # rubocop:disable Style/StructInheritance
5
+ def update?
6
+ post.user == user
7
+ end
8
+
9
+ def destroy?
10
+ false
11
+ end
12
+
13
+ def show?
14
+ true
15
+ end
16
+ end
17
+
18
+ class PostPolicy::Scope < Struct.new(:user, :scope) # rubocop:disable Style/StructInheritance, Style/ClassAndModuleChildren
19
+ def resolve
20
+ scope.published
21
+ end
22
+ end
23
+
24
+ class Post < Struct.new(:user) # rubocop:disable Style/StructInheritance
25
+ def self.published
26
+ :published
27
+ end
28
+
29
+ def to_s
30
+ 'Post'
31
+ end
32
+
33
+ def inspect
34
+ '#<Post>'
35
+ end
36
+ end
37
+
38
+ let(:user) { double }
39
+ let(:post) { Post.new(user) }
40
+
41
+ describe '.authorize' do
42
+ it 'infers the policy and authorizes based on it' do
43
+ expect(Sand.authorize(user, post, :update?)).to be_truthy
44
+ end
45
+
46
+ it 'raises an error with a query and action' do
47
+ expect { Sand.authorize(user, post, :destroy?) }.to raise_error(Sand::NotAuthorizedError, 'not allowed to destroy? this #<Post>') do |error|
48
+ expect(error.query).to eq :destroy?
49
+ expect(error.record).to eq post
50
+ expect(error.policy).to eq Sand.policy!(user, post)
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '.policy_scope' do
56
+ it 'returns an instantiated policy scope given a plain model class' do
57
+ expect(Sand.policy_scope(user, Post)).to eq :published
58
+ end
59
+
60
+ it 'uses Model.policy if it is defined' do
61
+ class NonStandardPolicyKlass < Struct.new(:user) # rubocop:disable Style/StructInheritance
62
+ class Scope < Struct.new(:user, :resource) # rubocop:disable Style/StructInheritance
63
+ def resolve
64
+ :resolved
65
+ end
66
+ end
67
+ end
68
+ class NonStandardKlass
69
+ def to_s
70
+ 'WillBreak'
71
+ end
72
+
73
+ def self.sand_policy
74
+ NonStandardPolicyKlass
75
+ end
76
+ end
77
+
78
+ expect(Sand.policy_scope(user, NonStandardKlass)).to eq(:resolved)
79
+ end
80
+ end
81
+
82
+ describe '.policy!' do
83
+ it 'rests on default NameErrors if policy does not exist' do
84
+ class Foo
85
+ end
86
+
87
+ expect do
88
+ Sand.policy!(user, Foo)
89
+ end.to raise_error Sand::NotDefinedError
90
+ end
91
+
92
+ it 'succesfully finds a policy if one is defined' do
93
+ policy = Sand.policy!(user, post)
94
+ expect(policy).to be_an_instance_of(PostPolicy)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'sand'
3
+ require 'pry'
4
+ require 'application/shared_application_examples'
5
+
6
+ ENV['RACK_ENV'] = 'test'
@@ -0,0 +1,47 @@
1
+ require 'rack'
2
+ require 'json'
3
+ require 'support/shared_application_code'
4
+
5
+ class SandApp # rubocop:disable
6
+ def json_response(data)
7
+ [200, {}, JSON.dump(data)]
8
+ end
9
+
10
+ def call(env)
11
+ request = Rack::Request.new(env)
12
+
13
+ case request.path_info
14
+ when %r{/accounts$}
15
+ id = /\d/.match(request.path_info)[0]
16
+ user = User[id]
17
+ accounts = env['sand'].policy_scope(user, Account)
18
+ json_response(accounts.map(&:to_hash))
19
+ when %r{/verify_scoped/failure}
20
+ [200, {}, [1, 2, 3]]
21
+ when %r{/verify_scoped/succeed}
22
+ accounts = env['sand'].policy_scope(user, Account)
23
+ json_response(accounts.map(&:to_hash))
24
+ when %r{/verify_scoped/pass}
25
+ env['sand'].skip_sand_scoping
26
+ [200, {}, ['yay']]
27
+ when %r{/verify_authorized/fail}
28
+ user = User.find('1')
29
+ account = Account.first
30
+ env['sand'].authorize(user, account, :will_fail_action)
31
+ [200, {}, ['yay']]
32
+ when %r{/verify_authorized/success}
33
+ user = User.find('1')
34
+ account = Account.first
35
+ env['sand'].authorize(user, account, :will_succeed_action)
36
+ [200, {}, ['yay']]
37
+ else
38
+ [404, {}, []]
39
+ end
40
+ end
41
+ end
42
+
43
+ MyRackApp = Rack::Builder.new do
44
+ use Sand::Middleware
45
+
46
+ run SandApp.new
47
+ end
@@ -0,0 +1,58 @@
1
+ require 'sequel'
2
+
3
+ DB = Sequel.sqlite
4
+
5
+ DB.create_table :users do
6
+ primary_key :id
7
+ String :name
8
+ Boolean :admin
9
+ end
10
+
11
+ DB.create_table :accounts do
12
+ primary_key :id
13
+ String :title
14
+ end
15
+
16
+ DB.create_table :roles do
17
+ Integer 'user_id'
18
+ Integer 'account_id'
19
+ String 'role'
20
+ end
21
+
22
+ class Account < Sequel::Model; end
23
+ class User < Sequel::Model; end
24
+ class Role < Sequel::Model
25
+ many_to_one :user
26
+ many_to_one :account
27
+ end
28
+
29
+ class AccountPolicy
30
+ def initialize(user, record)
31
+ @user = user
32
+ @record = record
33
+ end
34
+
35
+ def will_fail_action
36
+ false
37
+ end
38
+
39
+ def will_succeed_action
40
+ true
41
+ end
42
+
43
+ class Scope
44
+ attr_reader :user, :scope
45
+
46
+ def initialize(user, scope)
47
+ @user = user
48
+ @scope = scope
49
+ end
50
+
51
+ def resolve
52
+ return [] if user.nil?
53
+ return scope.all if user.admin
54
+
55
+ scope.join(:roles, account_id: :id).where(user_id: user.id)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,46 @@
1
+ require 'sinatra'
2
+ require 'sand'
3
+ require 'json'
4
+ require 'support/shared_application_code'
5
+
6
+ get '/' do
7
+ 'Index'
8
+ end
9
+
10
+ helpers Sand::Helpers
11
+ use Sand::Middleware
12
+
13
+ get '/users/:user_id/accounts' do
14
+ user = User[params[:user_id]]
15
+ accounts = policy_scope(user, Account)
16
+ send :erb, accounts.map(&:to_hash).to_json
17
+ end
18
+
19
+ get '/verify_scoped/fail' do
20
+ send :erb, Account.all.map(&:to_hash).to_json
21
+ end
22
+
23
+ get '/verify_scoped/succeed' do
24
+ user = User.find('1')
25
+ accounts = policy_scope(user, Account)
26
+ send :erb, accounts.map(&:to_hash).to_json
27
+ end
28
+
29
+ get '/verify_scoped/pass' do
30
+ skip_sand_scoping
31
+ 200
32
+ end
33
+
34
+ get '/verify_authorized/fail' do
35
+ user = User.find('1')
36
+ account = Account.first
37
+ authorize(user, account, :will_fail_action)
38
+ send :erb, account.to_json
39
+ end
40
+
41
+ get '/verify_authorized/success' do
42
+ user = User.find('1')
43
+ account = Account.first
44
+ authorize(user, account, :will_succeed_action)
45
+ send :erb, account.to_json
46
+ end
metadata ADDED
@@ -0,0 +1,234 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sand
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nick Tomlin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-18 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: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
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
+ - !ruby/object:Gem::Dependency
70
+ name: rubygems-tasks
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.37.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.37.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 0.10.3
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 0.10.3
111
+ - !ruby/object:Gem::Dependency
112
+ name: rack-test
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 0.6.3
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 0.6.3
125
+ - !ruby/object:Gem::Dependency
126
+ name: sinatra
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 1.4.7
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 1.4.7
139
+ - !ruby/object:Gem::Dependency
140
+ name: sequel
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '4.31'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '4.31'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sqlite3
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: A ruby gem for authorization for use in sinatra/rack applications. Heavily
168
+ inspired [Pundit](https://github.com/elabs/pundit)
169
+ email: nick.tomlin@gmail.com
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".document"
175
+ - ".gitignore"
176
+ - ".rdoc_options"
177
+ - ".rspec"
178
+ - ".rubocop.yml"
179
+ - ".travis.yml"
180
+ - ChangeLog.md
181
+ - Gemfile
182
+ - LICENSE.txt
183
+ - README.md
184
+ - Rakefile
185
+ - lib/sand.rb
186
+ - lib/sand/helpers.rb
187
+ - lib/sand/middleware.rb
188
+ - lib/sand/policy_finder.rb
189
+ - lib/sand/util.rb
190
+ - lib/sand/version.rb
191
+ - sand.gemspec
192
+ - spec/.rubocop.yml
193
+ - spec/application/rack_spec.rb
194
+ - spec/application/shared_application_examples.rb
195
+ - spec/application/sinatra_spec.rb
196
+ - spec/sand_spec.rb
197
+ - spec/spec_helper.rb
198
+ - spec/support/rack_app.rb
199
+ - spec/support/shared_application_code.rb
200
+ - spec/support/sinatra_app.rb
201
+ homepage: https://rubygems.org/gems/sand
202
+ licenses:
203
+ - MIT
204
+ metadata: {}
205
+ post_install_message:
206
+ rdoc_options: []
207
+ require_paths:
208
+ - lib
209
+ required_ruby_version: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ requirements: []
220
+ rubyforge_project:
221
+ rubygems_version: 2.4.5
222
+ signing_key:
223
+ specification_version: 4
224
+ summary: Authorization for rack-based applications
225
+ test_files:
226
+ - spec/.rubocop.yml
227
+ - spec/application/rack_spec.rb
228
+ - spec/application/shared_application_examples.rb
229
+ - spec/application/sinatra_spec.rb
230
+ - spec/sand_spec.rb
231
+ - spec/spec_helper.rb
232
+ - spec/support/rack_app.rb
233
+ - spec/support/shared_application_code.rb
234
+ - spec/support/sinatra_app.rb