wash_out 0.4.2 → 0.5.2
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.
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +7 -1
- data/README.md +6 -6
- data/app/helpers/wash_out_helper.rb +1 -1
- data/app/views/wash_with_soap/error.builder +4 -4
- data/app/views/wash_with_soap/wsdl.builder +2 -2
- data/gemfiles/rails-3.0.11.gemfile +1 -0
- data/gemfiles/rails-3.0.11.gemfile.lock +10 -2
- data/gemfiles/rails-3.1.3.gemfile +1 -0
- data/gemfiles/rails-3.1.3.gemfile.lock +10 -2
- data/lib/wash_out/dispatcher.rb +59 -12
- data/lib/wash_out/engine.rb +5 -1
- data/lib/wash_out/param.rb +4 -2
- data/lib/wash_out/version.rb +1 -1
- data/lib/wash_out/wsse.rb +79 -0
- data/lib/wash_out.rb +3 -2
- data/spec/wash_out/dispatcher_spec.rb +65 -0
- data/spec/wash_out_spec.rb +102 -0
- metadata +14 -12
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,22 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.5.2
|
4
|
+
|
5
|
+
* .NET-compliant response tags [@ebeigarts][]
|
6
|
+
* Tiny fixes [@ebeigarts][]
|
7
|
+
|
8
|
+
## 0.5.1
|
9
|
+
|
10
|
+
* Better routing points [@inossidabile][]
|
11
|
+
|
12
|
+
## 0.5.0
|
13
|
+
|
14
|
+
* WSSE password authentication [@dhinus][]
|
15
|
+
* Ruby 1.8 compatibility restores [@dhinus][]
|
16
|
+
|
3
17
|
## 0.4.2
|
4
18
|
|
19
|
+
* SOAP hrefs are now supported [@inossidabile][]
|
5
20
|
* Better camelization: reusable types and methods are now supported [@inossidabile][]
|
6
21
|
|
7
22
|
## 0.4.1
|
@@ -60,3 +75,5 @@
|
|
60
75
|
|
61
76
|
[@inossidabile]: https://twitter.com/#!/_inossidabile
|
62
77
|
[@rngtng]: https://github.com/rngtng
|
78
|
+
[@dhinus]: https://github.com/dhinus
|
79
|
+
[@ebeigarts]: https://github.com/ebeigarts
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
wash_out (0.
|
4
|
+
wash_out (0.5.2)
|
5
5
|
nori
|
6
6
|
|
7
7
|
GEM
|
@@ -50,6 +50,11 @@ GEM
|
|
50
50
|
coderay (~> 1.0.5)
|
51
51
|
method_source (~> 0.7.1)
|
52
52
|
slop (>= 2.4.4, < 3)
|
53
|
+
pry (0.9.8.4-java)
|
54
|
+
coderay (~> 1.0.5)
|
55
|
+
method_source (~> 0.7.1)
|
56
|
+
slop (>= 2.4.4, < 3)
|
57
|
+
spoon (~> 0.0)
|
53
58
|
rack (1.4.1)
|
54
59
|
rack-cache (1.1)
|
55
60
|
rack (>= 0.4)
|
@@ -89,6 +94,7 @@ GEM
|
|
89
94
|
nori (~> 1.1)
|
90
95
|
wasabi (~> 2.1)
|
91
96
|
slop (2.4.4)
|
97
|
+
spoon (0.0.1)
|
92
98
|
sprockets (2.1.2)
|
93
99
|
hike (~> 1.2)
|
94
100
|
rack (~> 1.0)
|
data/README.md
CHANGED
@@ -125,12 +125,10 @@ inside separate classes for the complex ones. Here's the way to do that:
|
|
125
125
|
|
126
126
|
```ruby
|
127
127
|
class Fluffy < WashOut::Type
|
128
|
-
map
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
}
|
133
|
-
)
|
128
|
+
map :universe => {
|
129
|
+
:name => :string,
|
130
|
+
:age => :int
|
131
|
+
}
|
134
132
|
end
|
135
133
|
|
136
134
|
class FluffyContainer < WashOut::Type
|
@@ -175,6 +173,8 @@ soap_action "foo" # this will be passed as is
|
|
175
173
|
|
176
174
|
* Björn Nilsson ([@Bjorn-Nilsson](https://github.com/Bjorn-Nilsson))
|
177
175
|
* Tobias Bielohlawek ([@rngtng](https://github.com/rngtng))
|
176
|
+
* Francesco Negri ([@dhinus](https://github.com/dhinus))
|
177
|
+
* Edgars Beigarts ([@ebeigarts](https://github.com/ebeigarts))
|
178
178
|
|
179
179
|
## LICENSE
|
180
180
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
xml.instruct!
|
2
|
-
xml.Envelope "xmlns:
|
3
|
-
|
4
|
-
xml.Body do
|
5
|
-
xml.Fault :encodingStyle => 'http://schemas.xmlsoap.org/soap/encoding/' do
|
2
|
+
xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envelope/',
|
3
|
+
"xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance' do
|
4
|
+
xml.tag! "soap:Body" do
|
5
|
+
xml.tag! "soap:Fault", :encodingStyle => 'http://schemas.xmlsoap.org/soap/encoding/' do
|
6
6
|
xml.faultcode "Server", 'xsi:type' => 'xsd:QName'
|
7
7
|
xml.faultstring error_message, 'xsi:type' => 'xsd:string'
|
8
8
|
end
|
@@ -23,7 +23,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
|
|
23
23
|
@map.keys.each do |operation|
|
24
24
|
xml.operation :name => operation do
|
25
25
|
xml.input :message => "tns:#{operation}"
|
26
|
-
xml.output :message => "tns:#{operation}_response"
|
26
|
+
xml.output :message => "tns:#{operation}#{WashOut::Engine.camelize_wsdl ? 'Response' : '_response'}"
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -59,7 +59,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
|
|
59
59
|
xml.part wsdl_occurence(p, true, :name => p.name, :type => p.namespaced_type)
|
60
60
|
end
|
61
61
|
end
|
62
|
-
xml.message :name => "#{operation}_response" do
|
62
|
+
xml.message :name => "#{operation}#{WashOut::Engine.camelize_wsdl ? 'Response' : '_response'}" do
|
63
63
|
formats[:out].each do |p|
|
64
64
|
xml.part wsdl_occurence(p, true, :name => p.name, :type => p.namespaced_type)
|
65
65
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote: /Users/
|
2
|
+
remote: /Users/inossidabile/Sites/wash_out
|
3
3
|
specs:
|
4
|
-
wash_out (0.2
|
4
|
+
wash_out (0.5.2)
|
5
5
|
nori
|
6
6
|
|
7
7
|
GEM
|
@@ -41,6 +41,7 @@ GEM
|
|
41
41
|
rake
|
42
42
|
arel (2.0.10)
|
43
43
|
builder (2.1.2)
|
44
|
+
coderay (1.0.7)
|
44
45
|
diff-lcs (1.1.3)
|
45
46
|
erubis (2.6.6)
|
46
47
|
abstract (>= 1.0.0)
|
@@ -55,10 +56,15 @@ GEM
|
|
55
56
|
i18n (>= 0.4.0)
|
56
57
|
mime-types (~> 1.16)
|
57
58
|
treetop (~> 1.4.8)
|
59
|
+
method_source (0.8)
|
58
60
|
mime-types (1.17.2)
|
59
61
|
nokogiri (1.5.0)
|
60
62
|
nori (1.0.2)
|
61
63
|
polyglot (0.3.3)
|
64
|
+
pry (0.9.10)
|
65
|
+
coderay (~> 1.0.5)
|
66
|
+
method_source (~> 0.8)
|
67
|
+
slop (~> 3.3.1)
|
62
68
|
rack (1.2.4)
|
63
69
|
rack-mount (0.6.14)
|
64
70
|
rack (>= 1.0.0)
|
@@ -102,6 +108,7 @@ GEM
|
|
102
108
|
nokogiri (>= 1.4.0)
|
103
109
|
nori (~> 1.0)
|
104
110
|
wasabi (~> 2.0)
|
111
|
+
slop (3.3.2)
|
105
112
|
thor (0.14.6)
|
106
113
|
treetop (1.4.10)
|
107
114
|
polyglot
|
@@ -115,6 +122,7 @@ PLATFORMS
|
|
115
122
|
|
116
123
|
DEPENDENCIES
|
117
124
|
appraisal
|
125
|
+
pry
|
118
126
|
rails (= 3.0.11)
|
119
127
|
rspec-rails
|
120
128
|
savon
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote: /Users/
|
2
|
+
remote: /Users/inossidabile/Sites/wash_out
|
3
3
|
specs:
|
4
|
-
wash_out (0.2
|
4
|
+
wash_out (0.5.2)
|
5
5
|
nori
|
6
6
|
|
7
7
|
GEM
|
@@ -42,6 +42,7 @@ GEM
|
|
42
42
|
rake
|
43
43
|
arel (2.2.1)
|
44
44
|
builder (3.0.0)
|
45
|
+
coderay (1.0.7)
|
45
46
|
diff-lcs (1.1.3)
|
46
47
|
erubis (2.7.0)
|
47
48
|
gyoku (0.4.4)
|
@@ -55,11 +56,16 @@ GEM
|
|
55
56
|
i18n (>= 0.4.0)
|
56
57
|
mime-types (~> 1.16)
|
57
58
|
treetop (~> 1.4.8)
|
59
|
+
method_source (0.8)
|
58
60
|
mime-types (1.17.2)
|
59
61
|
multi_json (1.0.4)
|
60
62
|
nokogiri (1.5.0)
|
61
63
|
nori (1.0.2)
|
62
64
|
polyglot (0.3.3)
|
65
|
+
pry (0.9.10)
|
66
|
+
coderay (~> 1.0.5)
|
67
|
+
method_source (~> 0.8)
|
68
|
+
slop (~> 3.3.1)
|
63
69
|
rack (1.3.5)
|
64
70
|
rack-cache (1.1)
|
65
71
|
rack (>= 0.4)
|
@@ -108,6 +114,7 @@ GEM
|
|
108
114
|
nokogiri (>= 1.4.0)
|
109
115
|
nori (~> 1.0)
|
110
116
|
wasabi (~> 2.0)
|
117
|
+
slop (3.3.2)
|
111
118
|
sprockets (2.0.3)
|
112
119
|
hike (~> 1.2)
|
113
120
|
rack (~> 1.0)
|
@@ -126,6 +133,7 @@ PLATFORMS
|
|
126
133
|
|
127
134
|
DEPENDENCIES
|
128
135
|
appraisal
|
136
|
+
pry
|
129
137
|
rails (= 3.1.3)
|
130
138
|
rspec-rails
|
131
139
|
savon
|
data/lib/wash_out/dispatcher.rb
CHANGED
@@ -12,9 +12,12 @@ module WashOut
|
|
12
12
|
# This filter parses the SOAP request and puts it into +params+ array.
|
13
13
|
def _parse_soap_parameters
|
14
14
|
# Do not interfere with project-space Nori setup
|
15
|
-
strip
|
16
|
-
convert
|
15
|
+
strip = Nori.strip_namespaces?
|
16
|
+
convert = Nori.convert_tags?
|
17
|
+
typecast = Nori.advanced_typecasting?
|
18
|
+
|
17
19
|
Nori.strip_namespaces = true
|
20
|
+
Nori.advanced_typecasting = false
|
18
21
|
|
19
22
|
if WashOut::Engine.snakecase_input
|
20
23
|
Nori.convert_tags_to { |tag| tag.snakecase.to_sym }
|
@@ -22,20 +25,45 @@ module WashOut
|
|
22
25
|
Nori.convert_tags_to { |tag| tag.to_sym }
|
23
26
|
end
|
24
27
|
|
25
|
-
|
28
|
+
request_body = request.body.read
|
29
|
+
@_params = Nori.parse(request_body)
|
30
|
+
|
31
|
+
references = WashOut::Dispatcher.deep_select(@_params){|k,v| v.is_a?(Hash) && v.has_key?(:@id)}
|
32
|
+
|
33
|
+
unless references.blank?
|
34
|
+
replaces = {}; references.each{|r| replaces['#'+r[:@id]] = r}
|
35
|
+
@_params = WashOut::Dispatcher.deep_replace_href(@_params, replaces)
|
36
|
+
end
|
26
37
|
|
27
38
|
# Reset Nori setup to project-space
|
28
39
|
Nori.strip_namespaces = strip
|
40
|
+
Nori.advanced_typecasting = typecast
|
29
41
|
Nori.convert_tags_to convert
|
30
42
|
end
|
31
43
|
|
44
|
+
def _authenticate_wsse
|
45
|
+
begin
|
46
|
+
xml_security = @_params.values_at(:envelope, :Envelope).compact.first
|
47
|
+
xml_security = xml_security.values_at(:header, :Header).compact.first
|
48
|
+
xml_security = xml_security.values_at(:security, :Security).compact.first
|
49
|
+
username_token = xml_security.values_at(:username_token, :UsernameToken).compact.first
|
50
|
+
rescue
|
51
|
+
username_token = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
WashOut::Wsse.authenticate username_token
|
55
|
+
|
56
|
+
request.env['WSSE_TOKEN'] = username_token.with_indifferent_access unless username_token.blank?
|
57
|
+
end
|
58
|
+
|
32
59
|
def _map_soap_parameters
|
33
60
|
soap_action = request.env['wash_out.soap_action']
|
34
61
|
action_spec = self.class.soap_actions[soap_action]
|
35
62
|
|
36
63
|
xml_data = @_params.values_at(:envelope, :Envelope).compact.first
|
37
64
|
xml_data = xml_data.values_at(:body, :Body).compact.first
|
38
|
-
xml_data = xml_data.values_at(soap_action.underscore.to_sym,
|
65
|
+
xml_data = xml_data.values_at(soap_action.underscore.to_sym,
|
66
|
+
soap_action.to_sym).compact.first || {}
|
39
67
|
|
40
68
|
strip_empty_nodes = lambda{|hash|
|
41
69
|
hash.each do |key, value|
|
@@ -52,9 +80,7 @@ module WashOut
|
|
52
80
|
|
53
81
|
hash
|
54
82
|
}
|
55
|
-
|
56
83
|
xml_data = strip_empty_nodes.call(xml_data)
|
57
|
-
|
58
84
|
@_params = HashWithIndifferentAccess.new
|
59
85
|
|
60
86
|
action_spec[:in].each do |param|
|
@@ -72,7 +98,7 @@ module WashOut
|
|
72
98
|
@namespace = WashOut::Engine.namespace
|
73
99
|
@name = controller_path.gsub('/', '_')
|
74
100
|
|
75
|
-
render :template => 'wash_with_soap/wsdl'
|
101
|
+
render :template => 'wash_with_soap/wsdl', :layout => false
|
76
102
|
end
|
77
103
|
|
78
104
|
# Render a SOAP response.
|
@@ -109,6 +135,7 @@ module WashOut
|
|
109
135
|
}
|
110
136
|
|
111
137
|
render :template => 'wash_with_soap/response',
|
138
|
+
:layout => false,
|
112
139
|
:locals => { :result => inject.call(result, action_spec) },
|
113
140
|
:content_type => 'text/xml'
|
114
141
|
end
|
@@ -118,27 +145,47 @@ module WashOut
|
|
118
145
|
render_soap_error("Cannot find SOAP action mapping for #{request.env['wash_out.soap_action']}")
|
119
146
|
end
|
120
147
|
|
148
|
+
def _render_soap_exception(error)
|
149
|
+
render_soap_error(error.message)
|
150
|
+
end
|
151
|
+
|
121
152
|
# Render a SOAP error response.
|
122
153
|
#
|
123
154
|
# Rails do not support sequental rescue_from handling, that is, rescuing an
|
124
155
|
# exception from a rescue_from handler. Hence this function is a public API.
|
125
156
|
def render_soap_error(message)
|
126
157
|
render :template => 'wash_with_soap/error', :status => 500,
|
158
|
+
:layout => false,
|
127
159
|
:locals => { :error_message => message },
|
128
160
|
:content_type => 'text/xml'
|
129
161
|
end
|
130
162
|
|
131
|
-
private
|
132
|
-
|
133
163
|
def self.included(controller)
|
134
164
|
controller.send :rescue_from, SOAPError, :with => :_render_soap_exception
|
135
165
|
controller.send :helper, :wash_out
|
136
166
|
controller.send :before_filter, :_parse_soap_parameters, :except => [ :_generate_wsdl, :_invalid_action ]
|
137
|
-
controller.send :before_filter, :
|
167
|
+
controller.send :before_filter, :_authenticate_wsse, :except => [ :_generate_wsdl, :_invalid_action ]
|
168
|
+
controller.send :before_filter, :_map_soap_parameters, :except => [ :_generate_wsdl, :_invalid_action ]
|
138
169
|
end
|
139
170
|
|
140
|
-
def
|
141
|
-
|
171
|
+
def self.deep_select(hash, result=[], &blk)
|
172
|
+
result += Hash[hash.select(&blk)].values
|
173
|
+
|
174
|
+
hash.each do |key, value|
|
175
|
+
result = deep_select(value, result, &blk) if value.is_a? Hash
|
176
|
+
end
|
177
|
+
|
178
|
+
result
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.deep_replace_href(hash, replace)
|
182
|
+
return replace[hash[:@href]] if hash.has_key?(:@href)
|
183
|
+
|
184
|
+
hash.keys.each do |key, value|
|
185
|
+
hash[key] = deep_replace_href(hash[key], replace) if hash[key].is_a?(Hash)
|
186
|
+
end
|
187
|
+
|
188
|
+
hash
|
142
189
|
end
|
143
190
|
end
|
144
191
|
end
|
data/lib/wash_out/engine.rb
CHANGED
@@ -3,6 +3,7 @@ module WashOut
|
|
3
3
|
class << self
|
4
4
|
attr_accessor :namespace
|
5
5
|
attr_accessor :snakecase, :snakecase_input, :camelize_wsdl
|
6
|
+
attr_accessor :wsse_username, :wsse_password
|
6
7
|
end
|
7
8
|
|
8
9
|
self.namespace = 'urn:WashOut'
|
@@ -11,6 +12,9 @@ module WashOut
|
|
11
12
|
self.snakecase_input = false
|
12
13
|
self.camelize_wsdl = false
|
13
14
|
|
15
|
+
self.wsse_username = nil
|
16
|
+
self.wsse_password = nil
|
17
|
+
|
14
18
|
config.wash_out = ActiveSupport::OrderedOptions.new
|
15
19
|
|
16
20
|
initializer "wash_out.configuration" do |app|
|
@@ -23,4 +27,4 @@ module WashOut
|
|
23
27
|
end
|
24
28
|
end
|
25
29
|
end
|
26
|
-
end
|
30
|
+
end
|
data/lib/wash_out/param.rb
CHANGED
@@ -63,7 +63,7 @@ module WashOut
|
|
63
63
|
when 'string'; :to_s
|
64
64
|
when 'integer'; :to_i
|
65
65
|
when 'double'; :to_f
|
66
|
-
when 'boolean';
|
66
|
+
when 'boolean'; lambda { |v| v == 'true' }
|
67
67
|
when 'date'; :to_date
|
68
68
|
when 'datetime'; :to_datetime
|
69
69
|
when 'time'; :to_time
|
@@ -74,8 +74,10 @@ module WashOut
|
|
74
74
|
data
|
75
75
|
elsif @multiplied
|
76
76
|
data.map{|x| x.send(operation)}
|
77
|
-
|
77
|
+
elsif operation.is_a? Symbol
|
78
78
|
data.send(operation)
|
79
|
+
else
|
80
|
+
operation.call(data)
|
79
81
|
end
|
80
82
|
end
|
81
83
|
end
|
data/lib/wash_out/version.rb
CHANGED
@@ -0,0 +1,79 @@
|
|
1
|
+
module WashOut
|
2
|
+
class Wsse
|
3
|
+
|
4
|
+
def self.authenticate(token)
|
5
|
+
wsse = self.new(token)
|
6
|
+
|
7
|
+
unless wsse.eligible?
|
8
|
+
raise WashOut::Dispatcher::SOAPError, "Unauthorized"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(token)
|
13
|
+
if token.blank? && required?
|
14
|
+
raise WashOut::Dispatcher::SOAPError, "Missing required UsernameToken"
|
15
|
+
end
|
16
|
+
@username_token = token
|
17
|
+
end
|
18
|
+
|
19
|
+
def required?
|
20
|
+
!WashOut::Engine.wsse_username.blank?
|
21
|
+
end
|
22
|
+
|
23
|
+
def expected_user
|
24
|
+
WashOut::Engine.wsse_username
|
25
|
+
end
|
26
|
+
|
27
|
+
def expected_password
|
28
|
+
WashOut::Engine.wsse_password
|
29
|
+
end
|
30
|
+
|
31
|
+
def matches_expected_digest?(password)
|
32
|
+
nonce = @username_token.values_at(:nonce, :Nonce).compact.first
|
33
|
+
timestamp = @username_token.values_at(:created, :Created).compact.first
|
34
|
+
|
35
|
+
return false if nonce.nil? || timestamp.nil?
|
36
|
+
|
37
|
+
# Token should not be accepted if timestamp is older than 5 minutes ago
|
38
|
+
# http://www.oasis-open.org/committees/download.php/16782/wss-v1.1-spec-os-UsernameTokenProfile.pdf
|
39
|
+
offset_in_minutes = ((DateTime.now - DateTime.parse(timestamp))* 24 * 60).to_i
|
40
|
+
return false if offset_in_minutes >= 5
|
41
|
+
|
42
|
+
# There are a few different implementations of the digest calculation
|
43
|
+
|
44
|
+
flavors = Array.new
|
45
|
+
|
46
|
+
# Ruby / Savon
|
47
|
+
token = nonce + timestamp + expected_password
|
48
|
+
flavors << Base64.encode64(Digest::SHA1.hexdigest(token)).chomp!
|
49
|
+
|
50
|
+
# Java
|
51
|
+
token = Base64.decode64(nonce) + timestamp + expected_password
|
52
|
+
flavors << Base64.encode64(Digest::SHA1.digest(token)).chomp!
|
53
|
+
|
54
|
+
flavors.each do |f|
|
55
|
+
return true if f == password
|
56
|
+
end
|
57
|
+
|
58
|
+
return false
|
59
|
+
end
|
60
|
+
|
61
|
+
def eligible?
|
62
|
+
return true unless required?
|
63
|
+
|
64
|
+
user = @username_token.values_at(:username, :Username).compact.first
|
65
|
+
password = @username_token.values_at(:password, :Password).compact.first
|
66
|
+
|
67
|
+
if (expected_user == user && expected_password == password)
|
68
|
+
return true
|
69
|
+
end
|
70
|
+
|
71
|
+
if (expected_user == user && matches_expected_digest?(password))
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
data/lib/wash_out.rb
CHANGED
@@ -5,6 +5,7 @@ require 'wash_out/soap'
|
|
5
5
|
require 'wash_out/router'
|
6
6
|
require 'wash_out/type'
|
7
7
|
require 'wash_out/model'
|
8
|
+
require 'wash_out/wsse'
|
8
9
|
|
9
10
|
module ActionDispatch::Routing
|
10
11
|
class Mapper
|
@@ -13,8 +14,8 @@ module ActionDispatch::Routing
|
|
13
14
|
options.reverse_merge!(@scope) if @scope
|
14
15
|
controller_class_name = [options[:module], controller_name].compact.join("/")
|
15
16
|
|
16
|
-
match "#{controller_name}/wsdl"
|
17
|
-
match "#{controller_name}/action" => WashOut::Router.new(controller_class_name), :defaults => { :action => '_action' }
|
17
|
+
match "#{controller_name}/wsdl" => "#{controller_name}#_generate_wsdl", :via => :get, :format => false
|
18
|
+
match "#{controller_name}/action" => WashOut::Router.new(controller_class_name), :defaults => { :controller => controller_class_name, :action => '_action' }, :format => false
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#encoding:utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe WashOut::Dispatcher do
|
6
|
+
|
7
|
+
class TestBody
|
8
|
+
attr_accessor :read
|
9
|
+
def initialize(read); @read = read; end
|
10
|
+
end
|
11
|
+
|
12
|
+
class TestRequest
|
13
|
+
attr_accessor :body
|
14
|
+
def initialize(body); @body = body; end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Dispatcher < ApplicationController
|
18
|
+
include WashOut::SOAP
|
19
|
+
|
20
|
+
def self.mock(text="")
|
21
|
+
dispatcher = self.new
|
22
|
+
dispatcher.request = TestRequest.new(TestBody.new(text))
|
23
|
+
dispatcher
|
24
|
+
end
|
25
|
+
|
26
|
+
def params
|
27
|
+
@_params
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "finds nested hashes" do
|
32
|
+
WashOut::Dispatcher.deep_select(:foo => 1){|k,v| k == :foo}.should == [1]
|
33
|
+
WashOut::Dispatcher.deep_select({:foo => {:foo => 1}}){|k,v| k == :foo}.should == [{:foo => 1}, 1]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "replaces nested hashed" do
|
37
|
+
WashOut::Dispatcher.deep_replace_href({:foo => {:@href => 1}}, {1 => 2}).should == {:foo => 2}
|
38
|
+
WashOut::Dispatcher.deep_replace_href({:bar => {:foo => {:@href => 1}}}, {1 => 2}).should == {:bar => {:foo => 2}}
|
39
|
+
end
|
40
|
+
|
41
|
+
it "parses typical request" do
|
42
|
+
dispatcher = Dispatcher.mock("<foo>1</foo>")
|
43
|
+
dispatcher._parse_soap_parameters
|
44
|
+
dispatcher.params.should == {:foo => "1"}
|
45
|
+
end
|
46
|
+
|
47
|
+
it "parses href request" do
|
48
|
+
dispatcher = Dispatcher.mock <<-XML
|
49
|
+
<request>
|
50
|
+
<entities href="#id1">
|
51
|
+
</entities>
|
52
|
+
</request>
|
53
|
+
<entity id="id1">
|
54
|
+
<foo><bar>1</bar></foo>
|
55
|
+
<sub href="#id2" />
|
56
|
+
</entity>
|
57
|
+
<ololo id="id2">
|
58
|
+
<foo>1</foo>
|
59
|
+
</ololo>
|
60
|
+
XML
|
61
|
+
dispatcher._parse_soap_parameters
|
62
|
+
dispatcher.params[:request][:entities].should == {:foo=>{:bar=>"1"}, :sub=>{:foo=>"1", :@id=>"id2"}, :@id=>"id1"}
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/spec/wash_out_spec.rb
CHANGED
@@ -507,4 +507,106 @@ describe WashOut do
|
|
507
507
|
}
|
508
508
|
end
|
509
509
|
end
|
510
|
+
|
511
|
+
describe "ws-security" do
|
512
|
+
|
513
|
+
it "should append username_token to params, if present" do
|
514
|
+
WashOut::Engine.wsse_username = nil
|
515
|
+
WashOut::Engine.wsse_password = nil
|
516
|
+
|
517
|
+
mock_controller do
|
518
|
+
soap_action "checkToken", :args => :integer, :return => nil, :to => 'check_token'
|
519
|
+
def check_token
|
520
|
+
request.env['WSSE_TOKEN']['username'].should == "gorilla"
|
521
|
+
request.env['WSSE_TOKEN']['password'].should == "secret"
|
522
|
+
render :soap => nil
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
client.request(:check_token) do
|
527
|
+
wsse.username = "gorilla"
|
528
|
+
wsse.password = "secret"
|
529
|
+
soap.body = { :value => 42 }
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
it "should handle PasswordText auth" do
|
534
|
+
WashOut::Engine.wsse_username = "gorilla"
|
535
|
+
WashOut::Engine.wsse_password = "secret"
|
536
|
+
|
537
|
+
mock_controller do
|
538
|
+
soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
|
539
|
+
def check_auth
|
540
|
+
render :soap => (params[:value] == 42)
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
# correct auth
|
545
|
+
lambda {
|
546
|
+
client.request(:check_auth) do
|
547
|
+
wsse.username = "gorilla"
|
548
|
+
wsse.password = "secret"
|
549
|
+
soap.body = { :value => 42 }
|
550
|
+
end
|
551
|
+
}.should_not raise_exception
|
552
|
+
# wrong user
|
553
|
+
lambda {
|
554
|
+
client.request(:check_auth) do
|
555
|
+
wsse.username = "chimpanzee"
|
556
|
+
wsse.password = "secret"
|
557
|
+
soap.body = { :value => 42 }
|
558
|
+
end
|
559
|
+
}.should raise_exception(Savon::SOAP::Fault)
|
560
|
+
# wrong pass
|
561
|
+
lambda {
|
562
|
+
client.request(:check_auth) do
|
563
|
+
wsse.username = "gorilla"
|
564
|
+
wsse.password = "nicetry"
|
565
|
+
soap.body = { :value => 42 }
|
566
|
+
end
|
567
|
+
}.should raise_exception(Savon::SOAP::Fault)
|
568
|
+
# no auth
|
569
|
+
lambda {
|
570
|
+
client.request(:check_auth) do
|
571
|
+
soap.body = { :value => 42 }
|
572
|
+
end
|
573
|
+
}.should raise_exception(Savon::SOAP::Fault)
|
574
|
+
end
|
575
|
+
|
576
|
+
it "should handle PasswordDigest auth" do
|
577
|
+
WashOut::Engine.wsse_username = "gorilla"
|
578
|
+
WashOut::Engine.wsse_password = "secret"
|
579
|
+
|
580
|
+
mock_controller do
|
581
|
+
soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
|
582
|
+
def check_auth
|
583
|
+
render :soap => (params[:value] == 42)
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
# correct auth
|
588
|
+
lambda {
|
589
|
+
client.request(:check_auth) do
|
590
|
+
wsse.credentials "gorilla", "secret", :digest
|
591
|
+
soap.body = { :value => 42 }
|
592
|
+
end
|
593
|
+
}.should_not raise_exception
|
594
|
+
# wrong user
|
595
|
+
lambda {
|
596
|
+
client.request(:check_auth) do
|
597
|
+
wsse.credentials "chimpanzee", "secret", :digest
|
598
|
+
soap.body = { :value => 42 }
|
599
|
+
end
|
600
|
+
}.should raise_exception(Savon::SOAP::Fault)
|
601
|
+
# wrong pass
|
602
|
+
lambda {
|
603
|
+
client.request(:check_auth) do
|
604
|
+
wsse.credentials "gorilla", "nicetry", :digest
|
605
|
+
soap.body = { :value => 42 }
|
606
|
+
end
|
607
|
+
}.should raise_exception(Savon::SOAP::Fault)
|
608
|
+
end
|
609
|
+
|
610
|
+
end
|
611
|
+
|
510
612
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wash_out
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-08-21 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: nori
|
17
|
-
requirement: &
|
17
|
+
requirement: &70188738989080 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70188738989080
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: rspec-rails
|
28
|
-
requirement: &
|
28
|
+
requirement: &70188738988660 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70188738988660
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: appraisal
|
39
|
-
requirement: &
|
39
|
+
requirement: &70188738988240 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: '0'
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *70188738988240
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: tzinfo
|
50
|
-
requirement: &
|
50
|
+
requirement: &70188738987780 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *70188738987780
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: savon
|
61
|
-
requirement: &
|
61
|
+
requirement: &70188738987360 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ! '>='
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
version: '0'
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *70188738987360
|
70
70
|
description: Dead simple Rails 3 SOAP server library
|
71
71
|
email: boris@roundlake.ru
|
72
72
|
executables: []
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- lib/wash_out/soap.rb
|
101
101
|
- lib/wash_out/type.rb
|
102
102
|
- lib/wash_out/version.rb
|
103
|
+
- lib/wash_out/wsse.rb
|
103
104
|
- spec/dummy/Rakefile
|
104
105
|
- spec/dummy/app/controllers/application_controller.rb
|
105
106
|
- spec/dummy/app/helpers/application_helper.rb
|
@@ -125,6 +126,7 @@ files:
|
|
125
126
|
- spec/dummy/script/rails
|
126
127
|
- spec/spec_helper.rb
|
127
128
|
- spec/support/httpi-rack.rb
|
129
|
+
- spec/wash_out/dispatcher_spec.rb
|
128
130
|
- spec/wash_out/param_spec.rb
|
129
131
|
- spec/wash_out/type_spec.rb
|
130
132
|
- spec/wash_out_spec.rb
|