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
         |