sinatra-bouncer 1.3.0 → 3.0.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 +4 -4
- data/.gitignore +2 -7
- data/.rubocop.yml +1 -9
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -3
- data/Gemfile.lock +92 -0
- data/README.md +231 -54
- data/RELEASE_NOTES.md +170 -0
- data/lib/sinatra/bouncer/basic_bouncer.rb +34 -37
- data/lib/sinatra/bouncer/rule.rb +114 -22
- data/lib/sinatra/bouncer/version.rb +1 -1
- data/lib/sinatra/bouncer.rb +6 -37
- data/sinatra_bouncer.gemspec +4 -1
- metadata +5 -14
- data/tests/integrations/dev_defines_legal_routes.feature +0 -57
- data/tests/integrations/dev_installs_bouncer.feature +0 -12
- data/tests/integrations/step_definitions/given.rb +0 -36
- data/tests/integrations/step_definitions/then.rb +0 -9
- data/tests/integrations/step_definitions/when.rb +0 -11
- data/tests/integrations/support/env.rb +0 -30
- data/tests/integrations/support/helpers.rb +0 -55
- data/tests/integrations/support/types.rb +0 -21
- data/tests/spec/basic_bouncer_spec.rb +0 -148
- data/tests/spec/rule_spec.rb +0 -67
- data/tests/spec/spec_helper.rb +0 -11
- data/tests/test_app.rb +0 -9
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
src_dir = File.expand_path('../../..', __dir__)
|
4
|
-
$LOAD_PATH.unshift(src_dir) unless $LOAD_PATH.include?(src_dir)
|
5
|
-
|
6
|
-
require 'simplecov'
|
7
|
-
|
8
|
-
SimpleCov.command_name 'spec'
|
9
|
-
|
10
|
-
require 'capybara/cucumber'
|
11
|
-
require 'rspec/expectations'
|
12
|
-
|
13
|
-
require 'tests/test_app'
|
14
|
-
|
15
|
-
# == CAPYBARA ==
|
16
|
-
Capybara.app = Sinatra::Application
|
17
|
-
|
18
|
-
# Set this to whatever the server's normal port is for you. Sinatra is 4567; rack 9292 by default.
|
19
|
-
# Also note: you have to be running the server for this to work.
|
20
|
-
Capybara.asset_host = 'http://localhost:4567'
|
21
|
-
|
22
|
-
# == REGULAR SETTINGS ==
|
23
|
-
Before do
|
24
|
-
Capybara.reset_sessions!
|
25
|
-
Capybara.app.settings.bouncer.instance_variable_get(:@ruleset).clear
|
26
|
-
|
27
|
-
@allowed_once_paths = []
|
28
|
-
end
|
29
|
-
|
30
|
-
World(RSpec::Matchers)
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Helper methods for Cucumber steps
|
4
|
-
module HelperMethods
|
5
|
-
# TEST_TMP_ROOT = Pathname.new(Dir.mktmpdir('bouncer_test_')).expand_path.freeze
|
6
|
-
# TEST_TMP_LOG = (TEST_TMP_ROOT / 'log').expand_path.freeze
|
7
|
-
|
8
|
-
# Data conversion helpers for Cucumber steps
|
9
|
-
module Conversion
|
10
|
-
def extract_list(list_string)
|
11
|
-
(list_string || '').split(',').map(&:strip)
|
12
|
-
end
|
13
|
-
|
14
|
-
def symrow(table)
|
15
|
-
table.symbolic_hashes.first
|
16
|
-
end
|
17
|
-
|
18
|
-
def symtable(table)
|
19
|
-
table.map_headers do |header|
|
20
|
-
header.tr(' ', '_').downcase.to_sym
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def parse_bool(string)
|
25
|
-
!(string =~ /t|y/i).nil?
|
26
|
-
end
|
27
|
-
|
28
|
-
def parse_phone(string)
|
29
|
-
string.to_s.split(/:\s+/)
|
30
|
-
end
|
31
|
-
|
32
|
-
def parse_duration(string)
|
33
|
-
scalar, unit = string.split(/\s/)
|
34
|
-
|
35
|
-
return nil if unit.nil? || unit.empty?
|
36
|
-
|
37
|
-
unit = "#{ unit }s" unless unit.end_with?('s')
|
38
|
-
|
39
|
-
unit_map = {
|
40
|
-
years: 365.25 * 86400,
|
41
|
-
months: 30 * 86400,
|
42
|
-
weeks: 7 * 86400,
|
43
|
-
days: 86400,
|
44
|
-
hours: 3600,
|
45
|
-
minutes: 60,
|
46
|
-
seconds: 1
|
47
|
-
}
|
48
|
-
|
49
|
-
scalar.to_i * unit_map[unit.downcase.to_sym]
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# Inject the HelperMethods into the Cucumber test context
|
55
|
-
World(HelperMethods, HelperMethods::Conversion)
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
ParameterType(name: 'path',
|
4
|
-
regexp: %r{/(?:\S+/?)*},
|
5
|
-
type: Pathname,
|
6
|
-
transformer: lambda do |str|
|
7
|
-
Pathname.new(str)
|
8
|
-
end)
|
9
|
-
|
10
|
-
ParameterType(name: 'boolean',
|
11
|
-
regexp: /(enabled|disabled|true|false|on|off|yes|no)/,
|
12
|
-
transformer: lambda do |str|
|
13
|
-
%w[enabled true on yes].include? str.downcase
|
14
|
-
end)
|
15
|
-
|
16
|
-
ParameterType(name: 'html element',
|
17
|
-
regexp: /<(\S+)>/,
|
18
|
-
type: String,
|
19
|
-
transformer: lambda do |str|
|
20
|
-
str
|
21
|
-
end)
|
@@ -1,148 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'spec_helper'
|
4
|
-
|
5
|
-
describe Sinatra::Bouncer::BasicBouncer do
|
6
|
-
let(:bouncer) { Sinatra::Bouncer::BasicBouncer.new }
|
7
|
-
|
8
|
-
describe '#can' do
|
9
|
-
it 'should raise an error if provided a block' do
|
10
|
-
msg = <<~ERR
|
11
|
-
You cannot provide a block to #can. If you wish to conditionally allow, use #can_sometimes instead.
|
12
|
-
ERR
|
13
|
-
|
14
|
-
expect do
|
15
|
-
bouncer.can(:post, 'some_path') do
|
16
|
-
# stub
|
17
|
-
end
|
18
|
-
end.to raise_error(Sinatra::Bouncer::BouncerError, msg.chomp)
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'should handle a list of paths' do
|
22
|
-
bouncer.can(:post, 'some_path', 'other_path')
|
23
|
-
|
24
|
-
expect(bouncer.can?(:post, 'some_path')).to be true
|
25
|
-
expect(bouncer.can?(:post, 'other_path')).to be true
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should accept a splat' do
|
29
|
-
bouncer.can(:post, 'directory/*')
|
30
|
-
|
31
|
-
expect(bouncer.can?(:post, 'directory/some_path')).to be true
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe '#can_sometimes' do
|
36
|
-
it 'should accept :any_method to mean all http methods' do
|
37
|
-
bouncer.can_sometimes(:any_method, 'some_path') do
|
38
|
-
true
|
39
|
-
end
|
40
|
-
|
41
|
-
expect(bouncer.can?(:get, 'some_path')).to be true
|
42
|
-
expect(bouncer.can?(:post, 'some_path')).to be true
|
43
|
-
expect(bouncer.can?(:put, 'some_path')).to be true
|
44
|
-
expect(bouncer.can?(:delete, 'some_path')).to be true
|
45
|
-
expect(bouncer.can?(:options, 'some_path')).to be true
|
46
|
-
expect(bouncer.can?(:link, 'some_path')).to be true
|
47
|
-
expect(bouncer.can?(:unlink, 'some_path')).to be true
|
48
|
-
expect(bouncer.can?(:head, 'some_path')).to be true
|
49
|
-
expect(bouncer.can?(:trace, 'some_path')).to be true
|
50
|
-
expect(bouncer.can?(:connect, 'some_path')).to be true
|
51
|
-
expect(bouncer.can?(:patch, 'some_path')).to be true
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'should accept :all to mean all paths' do
|
55
|
-
bouncer.can_sometimes(:get, :all) do
|
56
|
-
true
|
57
|
-
end
|
58
|
-
|
59
|
-
expect(bouncer.can?(:get, 'some_path')).to be true
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'should accept a list of paths' do
|
63
|
-
bouncer.can_sometimes(:post, 'some_path', 'other_path') do
|
64
|
-
true
|
65
|
-
end
|
66
|
-
|
67
|
-
expect(bouncer.can?(:post, 'some_path')).to be true
|
68
|
-
expect(bouncer.can?(:post, 'other_path')).to be true
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'should accept a splat' do
|
72
|
-
bouncer.can_sometimes(:post, 'directory/*') do
|
73
|
-
true
|
74
|
-
end
|
75
|
-
|
76
|
-
expect(bouncer.can?(:post, 'directory/some_path')).to be true
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'should not raise an error if provided a block' do
|
80
|
-
expect do
|
81
|
-
bouncer.can_sometimes(:any_method, 'some_path') do
|
82
|
-
true
|
83
|
-
end
|
84
|
-
end.to_not raise_error
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'should raise an error if not provided a block' do
|
88
|
-
msg = <<~ERR
|
89
|
-
You must provide a block to #can_sometimes. If you wish to always allow, use #can instead.
|
90
|
-
ERR
|
91
|
-
|
92
|
-
expect do
|
93
|
-
bouncer.can_sometimes(:any_method, 'some_path')
|
94
|
-
end.to raise_error(Sinatra::Bouncer::BouncerError, msg.chomp)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
describe '#can?' do
|
99
|
-
it 'should pass when declared allowed' do
|
100
|
-
bouncer.can(:any_method, 'some_path')
|
101
|
-
|
102
|
-
expect(bouncer.can?(:post, 'some_path')).to be true
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should fail when not declared allowed' do
|
106
|
-
expect(bouncer.can?(:post, 'some_path')).to be false
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'should pass if the rule block passes' do
|
110
|
-
bouncer.can_sometimes(:any_method, 'some_path') do
|
111
|
-
true
|
112
|
-
end
|
113
|
-
|
114
|
-
expect(bouncer.can?(:post, 'some_path')).to be true
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'should fail if the rule block fails' do
|
118
|
-
bouncer.can_sometimes(:any_method, 'some_path') do
|
119
|
-
false
|
120
|
-
end
|
121
|
-
|
122
|
-
expect(bouncer.can?(:post, 'some_path')).to be false
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
describe '#bounce' do
|
127
|
-
it 'should run the bounce_with block on sinatra instance' do
|
128
|
-
runner = nil
|
129
|
-
sinatra = double('sinatra')
|
130
|
-
|
131
|
-
bouncer.bounce_with = proc do
|
132
|
-
runner = self # self should be the sinatra double
|
133
|
-
end
|
134
|
-
|
135
|
-
bouncer.bounce(sinatra)
|
136
|
-
|
137
|
-
expect(runner).to be sinatra
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'should halt 403 if no block provided' do
|
141
|
-
app = double('sinatra')
|
142
|
-
|
143
|
-
expect(app).to receive(:halt).with(403)
|
144
|
-
|
145
|
-
bouncer.bounce(app)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
data/tests/spec/rule_spec.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'spec_helper'
|
4
|
-
|
5
|
-
describe Sinatra::Bouncer::Rule do
|
6
|
-
describe '#match_path?' do
|
7
|
-
it 'should match simple paths' do
|
8
|
-
rule = Sinatra::Bouncer::Rule.new('/some_path') { true }
|
9
|
-
|
10
|
-
expect(rule.match_path?('/some_path')).to be true
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'should append leading slashes to the given path' do
|
14
|
-
rule = Sinatra::Bouncer::Rule.new('some_path') { true }
|
15
|
-
|
16
|
-
expect(rule.match_path?('/some_path')).to be true
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should append leading slashes to the tested path' do
|
20
|
-
rule = Sinatra::Bouncer::Rule.new('/other_path') { true }
|
21
|
-
|
22
|
-
expect(rule.match_path?('other_path')).to be true
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'should match splats' do
|
26
|
-
rule = Sinatra::Bouncer::Rule.new('/directory/*') { true }
|
27
|
-
|
28
|
-
%w[/directory/one /directory/two /directory/three].each do |path|
|
29
|
-
expect(rule.match_path?(path)).to be true
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'should NOT match empty string to a splat' do
|
34
|
-
rule = Sinatra::Bouncer::Rule.new('/directory/*') { true }
|
35
|
-
|
36
|
-
expect(rule.match_path?('/directory/')).to be false
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should require that both paths are same length' do
|
40
|
-
rule = Sinatra::Bouncer::Rule.new('/directory/*') { true }
|
41
|
-
|
42
|
-
%w[/directory /directory/extra/length].each do |path|
|
43
|
-
expect(rule.match_path?(path)).to be false
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe '#rule_passes?' do
|
49
|
-
it 'should raise an error if rule returns nonbool' do
|
50
|
-
rule = Sinatra::Bouncer::Rule.new('/something') { nil }
|
51
|
-
|
52
|
-
expect { rule.rule_passes? }.to raise_error Sinatra::Bouncer::BouncerError
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'should return true when the block is true' do
|
56
|
-
rule = Sinatra::Bouncer::Rule.new('/something') { true }
|
57
|
-
|
58
|
-
expect(rule.rule_passes?).to be true
|
59
|
-
end
|
60
|
-
|
61
|
-
it 'should return true when the block is false' do
|
62
|
-
rule = Sinatra::Bouncer::Rule.new('/something') { false }
|
63
|
-
|
64
|
-
expect(rule.rule_passes?).to be false
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
data/tests/spec/spec_helper.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
src_dir = File.expand_path('../..', __dir__)
|
4
|
-
$LOAD_PATH.unshift(src_dir) unless $LOAD_PATH.include?(src_dir)
|
5
|
-
|
6
|
-
require 'simplecov'
|
7
|
-
|
8
|
-
SimpleCov.command_name 'spec'
|
9
|
-
|
10
|
-
require 'lib/sinatra/bouncer'
|
11
|
-
require 'rspec/matchers'
|