wash_out 0.4.2 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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.1)
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
- :universe => {
130
- :name => :string,
131
- :age => :int
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,7 +1,7 @@
1
1
  module WashOutHelper
2
2
  def wsdl_data(xml, params)
3
3
  params.each do |param|
4
- tag_name = "tns:#{param.name}"
4
+ tag_name = param.name
5
5
 
6
6
  if !param.struct?
7
7
  if !param.multiplied
@@ -1,8 +1,8 @@
1
1
  xml.instruct!
2
- xml.Envelope "xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance',
3
- :xmlns => 'http://schemas.xmlsoap.org/soap/envelope/' do
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
@@ -2,6 +2,7 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
+ gem "pry"
5
6
  gem "rails", "3.0.11"
6
7
 
7
8
  gemspec :path=>"../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/lovchy/Sites/wash_out
2
+ remote: /Users/inossidabile/Sites/wash_out
3
3
  specs:
4
- wash_out (0.2.3)
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
@@ -2,6 +2,7 @@
2
2
 
3
3
  source "http://rubygems.org"
4
4
 
5
+ gem "pry"
5
6
  gem "rails", "3.1.3"
6
7
 
7
8
  gemspec :path=>"../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
- remote: /Users/lovchy/Sites/wash_out
2
+ remote: /Users/inossidabile/Sites/wash_out
3
3
  specs:
4
- wash_out (0.2.3)
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
@@ -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 = Nori.strip_namespaces?
16
- convert = Nori.convert_tags?
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
- @_params = Nori.parse(request.body.read)
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, soap_action.to_sym).compact.first || {}
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, :_map_soap_parameters, :except => [ :_generate_wsdl, :_invalid_action ]
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 _render_soap_exception(error)
141
- render_soap_error(error.message)
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
@@ -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
@@ -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'; nil # Nori handles that for us
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
- else
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
@@ -1,3 +1,3 @@
1
1
  module WashOut
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.2"
3
3
  end
@@ -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" => "#{controller_name}#_generate_wsdl", :via => :get
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
@@ -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.2
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-05-21 00:00:00.000000000 Z
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: &70248126040800 !ruby/object:Gem::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: *70248126040800
25
+ version_requirements: *70188738989080
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rspec-rails
28
- requirement: &70248126040380 !ruby/object:Gem::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: *70248126040380
36
+ version_requirements: *70188738988660
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: appraisal
39
- requirement: &70248126039960 !ruby/object:Gem::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: *70248126039960
47
+ version_requirements: *70188738988240
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: tzinfo
50
- requirement: &70248126055900 !ruby/object:Gem::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: *70248126055900
58
+ version_requirements: *70188738987780
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: savon
61
- requirement: &70248126055480 !ruby/object:Gem::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: *70248126055480
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