puppet 2.7.17 → 2.7.18
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- data/CHANGELOG +16 -0
- data/conf/redhat/puppet.spec +4 -1
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application/master.rb +26 -8
- data/lib/puppet/defaults.rb +4 -4
- data/lib/puppet/face/file/download.rb +1 -1
- data/lib/puppet/file_bucket/file.rb +6 -7
- data/lib/puppet/file_serving/configuration.rb +2 -1
- data/lib/puppet/file_serving/content.rb +1 -2
- data/lib/puppet/file_serving/metadata.rb +1 -2
- data/lib/puppet/file_serving/mount/modules.rb +4 -5
- data/lib/puppet/file_serving/{indirection_hooks.rb → terminus_selector.rb} +2 -5
- data/lib/puppet/indirector/file_bucket_file/selector.rb +49 -0
- data/lib/puppet/indirector/file_content/selector.rb +30 -0
- data/lib/puppet/indirector/file_metadata/selector.rb +30 -0
- data/lib/puppet/network/authstore.rb +10 -2
- data/lib/puppet/reports/store.rb +13 -6
- data/lib/puppet/ssl/base.rb +8 -0
- data/lib/puppet/ssl/certificate_authority.rb +10 -0
- data/lib/puppet/ssl/certificate_authority/interface.rb +4 -2
- data/lib/puppet/ssl/host.rb +1 -0
- data/spec/integration/file_bucket/file_spec.rb +44 -0
- data/spec/integration/file_serving/content_spec.rb +3 -8
- data/spec/integration/file_serving/metadata_spec.rb +4 -9
- data/spec/integration/network/rest_authconfig_spec.rb +22 -3
- data/spec/shared_behaviours/file_serving.rb +70 -58
- data/spec/shared_behaviours/file_serving_model.rb +73 -0
- data/spec/unit/file_serving/configuration_spec.rb +37 -29
- data/spec/unit/file_serving/content_spec.rb +1 -5
- data/spec/unit/file_serving/metadata_spec.rb +1 -5
- data/spec/unit/file_serving/mount/modules_spec.rb +8 -0
- data/spec/unit/file_serving/{indirection_hooks_spec.rb → terminus_selector_spec.rb} +10 -11
- data/spec/unit/indirector/file_bucket_file/selector_spec.rb +29 -0
- data/spec/unit/indirector/file_content/selector_spec.rb +10 -0
- data/spec/unit/indirector/file_metadata/selector_spec.rb +11 -0
- data/spec/unit/network/handler/ca_spec.rb +1 -0
- data/spec/unit/reports/store_spec.rb +28 -0
- data/spec/unit/ssl/certificate_authority/interface_spec.rb +17 -17
- data/spec/unit/ssl/certificate_authority_spec.rb +76 -11
- metadata +15 -8
- data/lib/puppet/file_bucket/file/indirection_hooks.rb +0 -9
data/lib/puppet/ssl/base.rb
CHANGED
@@ -5,6 +5,9 @@ class Puppet::SSL::Base
|
|
5
5
|
# For now, use the YAML separator.
|
6
6
|
SEPARATOR = "\n---\n"
|
7
7
|
|
8
|
+
# Only allow printing ascii characters, excluding /
|
9
|
+
VALID_CERTNAME = /\A[ -.0-~]+\Z/
|
10
|
+
|
8
11
|
def self.from_multiple_s(text)
|
9
12
|
text.split(SEPARATOR).collect { |inst| from_s(inst) }
|
10
13
|
end
|
@@ -22,6 +25,10 @@ class Puppet::SSL::Base
|
|
22
25
|
@wrapped_class
|
23
26
|
end
|
24
27
|
|
28
|
+
def self.validate_certname(name)
|
29
|
+
raise "Certname #{name.inspect} must not contain unprintable or non-ASCII characters" unless name =~ VALID_CERTNAME
|
30
|
+
end
|
31
|
+
|
25
32
|
attr_accessor :name, :content
|
26
33
|
|
27
34
|
# Is this file for the CA?
|
@@ -35,6 +42,7 @@ class Puppet::SSL::Base
|
|
35
42
|
|
36
43
|
def initialize(name)
|
37
44
|
@name = name.to_s.downcase
|
45
|
+
self.class.validate_certname(@name)
|
38
46
|
end
|
39
47
|
|
40
48
|
# Read content from disk appropriately.
|
@@ -303,6 +303,16 @@ class Puppet::SSL::CertificateAuthority
|
|
303
303
|
raise CertificateSigningError.new(hostname), "CSR has request extensions that are not permitted: #{names}"
|
304
304
|
end
|
305
305
|
|
306
|
+
# Do not sign misleading CSRs
|
307
|
+
cn = csr.content.subject.to_a.assoc("CN")[1]
|
308
|
+
if hostname != cn
|
309
|
+
raise CertificateSigningError.new(hostname), "CSR subject common name #{cn.inspect} does not match expected certname #{hostname.inspect}"
|
310
|
+
end
|
311
|
+
|
312
|
+
if hostname !~ Puppet::SSL::Base::VALID_CERTNAME
|
313
|
+
raise CertificateSigningError.new(hostname), "CSR #{hostname.inspect} subject contains unprintable or non-ASCII characters"
|
314
|
+
end
|
315
|
+
|
306
316
|
# Wildcards: we don't allow 'em at any point.
|
307
317
|
#
|
308
318
|
# The stringification here makes the content visible, and saves us having
|
@@ -88,6 +88,8 @@ module Puppet
|
|
88
88
|
names = certs.values.map(&:keys).flatten
|
89
89
|
|
90
90
|
name_width = names.sort_by(&:length).last.length rescue 0
|
91
|
+
# We quote these names, so account for those characters
|
92
|
+
name_width += 2
|
91
93
|
|
92
94
|
output = [:request, :signed, :invalid].map do |type|
|
93
95
|
next if certs[type].empty?
|
@@ -113,11 +115,11 @@ module Puppet
|
|
113
115
|
|
114
116
|
alt_names.delete(host)
|
115
117
|
|
116
|
-
alt_str = "(alt names: #{alt_names.join(', ')})" unless alt_names.empty?
|
118
|
+
alt_str = "(alt names: #{alt_names.map(&:inspect).join(', ')})" unless alt_names.empty?
|
117
119
|
|
118
120
|
glyph = {:signed => '+', :request => ' ', :invalid => '-'}[type]
|
119
121
|
|
120
|
-
name = host.ljust(width)
|
122
|
+
name = host.inspect.ljust(width)
|
121
123
|
fingerprint = "(#{ca.fingerprint(host, @digest)})"
|
122
124
|
|
123
125
|
explanation = "(#{verify_error})" if verify_error
|
data/lib/puppet/ssl/host.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
require 'puppet/file_bucket/file'
|
6
|
+
|
7
|
+
describe Puppet::FileBucket::File do
|
8
|
+
describe "#indirection" do
|
9
|
+
before :each do
|
10
|
+
# Never connect to the network, no matter what
|
11
|
+
described_class.indirection.terminus(:rest).class.any_instance.stubs(:find)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "when running the master application" do
|
15
|
+
before :each do
|
16
|
+
Puppet::Application[:master].setup_terminuses
|
17
|
+
end
|
18
|
+
|
19
|
+
{
|
20
|
+
"md5/d41d8cd98f00b204e9800998ecf8427e" => :file,
|
21
|
+
"https://puppetmaster:8140/production/file_bucket_file/md5/d41d8cd98f00b204e9800998ecf8427e" => :file,
|
22
|
+
}.each do |key, terminus|
|
23
|
+
it "should use the #{terminus} terminus when requesting #{key.inspect}" do
|
24
|
+
described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
|
25
|
+
|
26
|
+
described_class.indirection.find(key)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "when running another application" do
|
32
|
+
{
|
33
|
+
"md5/d41d8cd98f00b204e9800998ecf8427e" => :file,
|
34
|
+
"https://puppetmaster:8140/production/file_bucket_file/md5/d41d8cd98f00b204e9800998ecf8427e" => :rest,
|
35
|
+
}.each do |key, terminus|
|
36
|
+
it "should use the #{terminus} terminus when requesting #{key.inspect}" do
|
37
|
+
described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
|
38
|
+
|
39
|
+
described_class.indirection.find(key)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,14 +1,9 @@
|
|
1
1
|
#!/usr/bin/env rspec
|
2
|
+
|
2
3
|
require 'spec_helper'
|
3
4
|
|
4
5
|
require 'puppet/file_serving/content'
|
5
|
-
require 'shared_behaviours/file_serving'
|
6
|
-
|
7
|
-
describe Puppet::FileServing::Content, " when finding files" do
|
8
|
-
it_should_behave_like "Puppet::FileServing::Files"
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
@indirection = Puppet::FileServing::Content.indirection
|
13
|
-
end
|
7
|
+
describe Puppet::FileServing::Content do
|
8
|
+
it_should_behave_like "a file_serving model"
|
14
9
|
end
|
@@ -1,15 +1,10 @@
|
|
1
1
|
#!/usr/bin/env rspec
|
2
|
+
|
2
3
|
require 'spec_helper'
|
3
4
|
|
4
5
|
require 'puppet/file_serving/metadata'
|
5
|
-
require 'shared_behaviours/file_serving'
|
6
|
-
require 'puppet/indirector/file_metadata/file_server'
|
7
|
-
|
8
|
-
describe Puppet::FileServing::Metadata, " when finding files" do
|
9
|
-
it_should_behave_like "Puppet::FileServing::Files"
|
10
6
|
|
11
|
-
|
12
|
-
|
13
|
-
@indirection = Puppet::FileServing::Metadata.indirection
|
14
|
-
end
|
7
|
+
describe Puppet::FileServing::Metadata do
|
8
|
+
it_should_behave_like "a file_serving model"
|
15
9
|
end
|
10
|
+
|
@@ -44,12 +44,31 @@ describe Puppet::Network::RestAuthConfig do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def request(args = {})
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
args = {
|
48
|
+
:key => 'key',
|
49
|
+
:node => 'host.domain.com',
|
50
|
+
:ip => '10.1.1.1',
|
51
|
+
:authenticated => true
|
52
|
+
}.merge(args)
|
50
53
|
['test', :find, args[:key], args]
|
51
54
|
end
|
52
55
|
|
56
|
+
it "should warn when matching against IP addresses" do
|
57
|
+
add_rule("allow 10.1.1.1")
|
58
|
+
|
59
|
+
@auth.should allow(request)
|
60
|
+
|
61
|
+
@logs.should be_any {|log| log.level == :warning and log.message =~ /Authentication based on IP address is deprecated/}
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not warn when matches against IP addresses fail" do
|
65
|
+
add_rule("allow 10.1.1.2")
|
66
|
+
|
67
|
+
@auth.should_not allow(request)
|
68
|
+
|
69
|
+
@logs.should_not be_any {|log| log.level == :warning and log.message =~ /Authentication based on IP address is deprecated/}
|
70
|
+
end
|
71
|
+
|
53
72
|
it "should support IPv4 address" do
|
54
73
|
add_rule("allow 10.1.1.1")
|
55
74
|
|
@@ -1,68 +1,80 @@
|
|
1
1
|
#!/usr/bin/env rspec
|
2
|
-
shared_examples_for "Puppet::FileServing::Files" do
|
3
|
-
it "should use the rest terminus when the 'puppet' URI scheme is used and a host name is present" do
|
4
|
-
uri = "puppet://myhost/fakemod/my/file"
|
5
|
-
|
6
|
-
# It appears that the mocking somehow interferes with the caching subsystem.
|
7
|
-
# This mock somehow causes another terminus to get generated.
|
8
|
-
term = @indirection.terminus(:rest)
|
9
|
-
@indirection.stubs(:terminus).with(:rest).returns term
|
10
|
-
term.expects(:find)
|
11
|
-
@indirection.find(uri)
|
12
|
-
end
|
13
2
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
Puppet.settings.stubs(:value).with(:name).returns("puppetd")
|
18
|
-
Puppet.settings.stubs(:value).with(:modulepath).returns("")
|
19
|
-
@indirection.terminus(:rest).expects(:find)
|
20
|
-
@indirection.find(uri)
|
21
|
-
end
|
3
|
+
shared_examples_for "Puppet::FileServing::Files" do |indirection|
|
4
|
+
%w[find search].each do |method|
|
5
|
+
let(:request) { Puppet::Indirector::Request.new(indirection, method, 'foo') }
|
22
6
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
Puppet.settings.stubs(:value).with(:name).returns("puppet")
|
28
|
-
Puppet.settings.stubs(:value).with(:fileserverconfig).returns("/whatever")
|
29
|
-
@indirection.terminus(:file_server).expects(:find)
|
30
|
-
@indirection.terminus(:file_server).stubs(:authorized?).returns(true)
|
31
|
-
@indirection.find(uri)
|
32
|
-
end
|
7
|
+
before :each do
|
8
|
+
# Stub this so we can set the :name setting
|
9
|
+
Puppet::Util::Settings::ReadOnly.stubs(:include?)
|
10
|
+
end
|
33
11
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
Puppet.settings.stubs(:value).returns ""
|
38
|
-
Puppet.settings.stubs(:value).with(:name).returns("apply")
|
39
|
-
Puppet.settings.stubs(:value).with(:fileserverconfig).returns("/whatever")
|
40
|
-
@indirection.terminus(:file_server).expects(:find)
|
41
|
-
@indirection.terminus(:file_server).stubs(:authorized?).returns(true)
|
42
|
-
@indirection.find(uri)
|
43
|
-
end
|
12
|
+
describe "##{method}" do
|
13
|
+
it "should proxy to file terminus if the path is absolute" do
|
14
|
+
request.key = make_absolute('/tmp/foo')
|
44
15
|
|
45
|
-
|
46
|
-
uri = Puppet::Util.path_to_uri(File.expand_path('/fakemod/my/other file'))
|
47
|
-
uri.scheme.should == 'file'
|
48
|
-
@indirection.terminus(:file).expects(:find)
|
49
|
-
@indirection.find(uri.to_s)
|
50
|
-
end
|
16
|
+
described_class.indirection.terminus(:file).class.any_instance.expects(method).with(request)
|
51
17
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
18
|
+
subject.send(method, request)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should proxy to file terminus if the protocol is file" do
|
22
|
+
request.protocol = 'file'
|
23
|
+
|
24
|
+
described_class.indirection.terminus(:file).class.any_instance.expects(method).with(request)
|
25
|
+
|
26
|
+
subject.send(method, request)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "when the protocol is puppet" do
|
30
|
+
before :each do
|
31
|
+
request.protocol = 'puppet'
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "and a server is specified" do
|
35
|
+
before :each do
|
36
|
+
request.server = 'puppet_server'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should proxy to rest terminus if we're 'apply'" do
|
40
|
+
Puppet[:name] = 'apply'
|
41
|
+
|
42
|
+
described_class.indirection.terminus(:rest).class.any_instance.expects(method).with(request)
|
43
|
+
|
44
|
+
subject.send(method, request)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should proxy to rest terminus if we aren't 'apply'" do
|
48
|
+
Puppet[:name] = 'not_apply'
|
49
|
+
|
50
|
+
described_class.indirection.terminus(:rest).class.any_instance.expects(method).with(request)
|
51
|
+
|
52
|
+
subject.send(method, request)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "and no server is specified" do
|
57
|
+
before :each do
|
58
|
+
request.server = nil
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should proxy to file_server if we're 'apply'" do
|
62
|
+
Puppet[:name] = 'apply'
|
63
|
+
|
64
|
+
described_class.indirection.terminus(:file_server).class.any_instance.expects(method).with(request)
|
65
|
+
|
66
|
+
subject.send(method, request)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should proxy to rest if we're not 'apply'" do
|
70
|
+
Puppet[:name] = 'not_apply'
|
57
71
|
|
58
|
-
|
59
|
-
uri = "fakemod/my/file"
|
60
|
-
mount = mock 'mount'
|
61
|
-
config = stub 'configuration', :split_path => [mount, "eh"]
|
62
|
-
@indirection.terminus(:file_server).stubs(:configuration).returns config
|
72
|
+
described_class.indirection.terminus(:rest).class.any_instance.expects(method).with(request)
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
|
74
|
+
subject.send(method, request)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
67
79
|
end
|
68
80
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
|
3
|
+
shared_examples_for "a file_serving model" do
|
4
|
+
include PuppetSpec::Files
|
5
|
+
|
6
|
+
describe "#indirection" do
|
7
|
+
before :each do
|
8
|
+
# Never connect to the network, no matter what
|
9
|
+
described_class.indirection.terminus(:rest).class.any_instance.stubs(:find)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "when running the master application" do
|
13
|
+
before :each do
|
14
|
+
Puppet::Application[:master].setup_terminuses
|
15
|
+
end
|
16
|
+
|
17
|
+
{
|
18
|
+
"/etc/sudoers" => :file_server,
|
19
|
+
"file:///etc/sudoers" => :file_server,
|
20
|
+
"puppet:///modules/foo/bar" => :file_server,
|
21
|
+
"puppet://server/modules/foo/bar" => :file_server,
|
22
|
+
}.each do |key, terminus|
|
23
|
+
it "should use the #{terminus} terminus when requesting #{key.inspect}" do
|
24
|
+
described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
|
25
|
+
|
26
|
+
described_class.indirection.find(key)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "when running the apply application" do
|
32
|
+
before :each do
|
33
|
+
# Stub this so we can set the 'name' setting
|
34
|
+
Puppet::Util::Settings::ReadOnly.stubs(:include?)
|
35
|
+
Puppet[:name] = 'apply'
|
36
|
+
end
|
37
|
+
|
38
|
+
{
|
39
|
+
"/etc/sudoers" => :file,
|
40
|
+
"file:///etc/sudoers" => :file,
|
41
|
+
"puppet:///modules/foo/bar" => :file_server,
|
42
|
+
"puppet://server/modules/foo/bar" => :rest,
|
43
|
+
}.each do |key, terminus|
|
44
|
+
it "should use the #{terminus} terminus when requesting #{key.inspect}" do
|
45
|
+
described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
|
46
|
+
|
47
|
+
described_class.indirection.find(key)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "when running another application" do
|
53
|
+
before :each do
|
54
|
+
# Stub this so we can set the 'name' setting
|
55
|
+
Puppet::Util::Settings::ReadOnly.stubs(:include?)
|
56
|
+
Puppet[:name] = 'agent'
|
57
|
+
end
|
58
|
+
|
59
|
+
{
|
60
|
+
"/etc/sudoers" => :file,
|
61
|
+
"file:///etc/sudoers" => :file,
|
62
|
+
"puppet:///modules/foo/bar" => :rest,
|
63
|
+
"puppet://server/modules/foo/bar" => :rest,
|
64
|
+
}.each do |key, terminus|
|
65
|
+
it "should use the #{terminus} terminus when requesting #{key.inspect}" do
|
66
|
+
described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
|
67
|
+
|
68
|
+
described_class.indirection.find(key)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -158,80 +158,88 @@ describe Puppet::FileServing::Configuration do
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
-
describe "
|
162
|
-
|
163
|
-
|
164
|
-
@config.stubs(:find_mount)
|
161
|
+
describe "#split_path" do
|
162
|
+
let(:config) { Puppet::FileServing::Configuration.configuration }
|
163
|
+
let(:request) { stub 'request', :key => "foo/bar/baz", :options => {}, :node => nil, :environment => mock("env") }
|
165
164
|
|
166
|
-
|
165
|
+
before do
|
166
|
+
config.stubs(:find_mount)
|
167
167
|
end
|
168
168
|
|
169
169
|
it "should reread the configuration" do
|
170
|
-
|
170
|
+
config.expects(:readconfig)
|
171
171
|
|
172
|
-
|
172
|
+
config.split_path(request)
|
173
173
|
end
|
174
174
|
|
175
175
|
it "should treat the first field of the URI path as the mount name" do
|
176
|
-
|
176
|
+
config.expects(:find_mount).with { |name, node| name == "foo" }
|
177
177
|
|
178
|
-
|
178
|
+
config.split_path(request)
|
179
179
|
end
|
180
180
|
|
181
181
|
it "should fail if the mount name is not alpha-numeric" do
|
182
|
-
|
182
|
+
request.expects(:key).returns "foo&bar/asdf"
|
183
183
|
|
184
|
-
lambda {
|
184
|
+
lambda { config.split_path(request) }.should raise_error(ArgumentError)
|
185
185
|
end
|
186
186
|
|
187
187
|
it "should support dashes in the mount name" do
|
188
|
-
|
188
|
+
request.expects(:key).returns "foo-bar/asdf"
|
189
189
|
|
190
|
-
lambda {
|
190
|
+
lambda { config.split_path(request) }.should_not raise_error(ArgumentError)
|
191
191
|
end
|
192
192
|
|
193
193
|
it "should use the mount name and environment to find the mount" do
|
194
|
-
|
195
|
-
|
194
|
+
config.expects(:find_mount).with { |name, env| name == "foo" and env == request.environment }
|
195
|
+
request.stubs(:node).returns("mynode")
|
196
196
|
|
197
|
-
|
197
|
+
config.split_path(request)
|
198
198
|
end
|
199
199
|
|
200
200
|
it "should return nil if the mount cannot be found" do
|
201
|
-
|
201
|
+
config.expects(:find_mount).returns nil
|
202
202
|
|
203
|
-
|
203
|
+
config.split_path(request).should be_nil
|
204
204
|
end
|
205
205
|
|
206
206
|
it "should return the mount and the relative path if the mount is found" do
|
207
207
|
mount = stub 'mount', :name => "foo"
|
208
|
-
|
208
|
+
config.expects(:find_mount).returns mount
|
209
209
|
|
210
|
-
|
210
|
+
config.split_path(request).should == [mount, "bar/baz"]
|
211
211
|
end
|
212
212
|
|
213
213
|
it "should remove any double slashes" do
|
214
|
-
|
214
|
+
request.stubs(:key).returns "foo/bar//baz"
|
215
215
|
mount = stub 'mount', :name => "foo"
|
216
|
-
|
216
|
+
config.expects(:find_mount).returns mount
|
217
|
+
|
218
|
+
config.split_path(request).should == [mount, "bar/baz"]
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should fail if the path contains .." do
|
222
|
+
request.stubs(:key).returns 'module/foo/../../bar'
|
217
223
|
|
218
|
-
|
224
|
+
expect do
|
225
|
+
config.split_path(request)
|
226
|
+
end.to raise_error(ArgumentError, /Invalid relative path/)
|
219
227
|
end
|
220
228
|
|
221
229
|
it "should return the relative path as nil if it is an empty string" do
|
222
|
-
|
230
|
+
request.expects(:key).returns "foo"
|
223
231
|
mount = stub 'mount', :name => "foo"
|
224
|
-
|
232
|
+
config.expects(:find_mount).returns mount
|
225
233
|
|
226
|
-
|
234
|
+
config.split_path(request).should == [mount, nil]
|
227
235
|
end
|
228
236
|
|
229
237
|
it "should add 'modules/' to the relative path if the modules mount is used but not specified, for backward compatibility" do
|
230
|
-
|
238
|
+
request.expects(:key).returns "foo/bar"
|
231
239
|
mount = stub 'mount', :name => "modules"
|
232
|
-
|
240
|
+
config.expects(:find_mount).returns mount
|
233
241
|
|
234
|
-
|
242
|
+
config.split_path(request).should == [mount, "foo/bar"]
|
235
243
|
end
|
236
244
|
end
|
237
245
|
end
|