hoodoo 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
 - data/lib/hoodoo/client/headers.rb +33 -0
 - data/lib/hoodoo/services/middleware/middleware.rb +172 -3
 - data/lib/hoodoo/version.rb +1 -1
 - data/spec/client/client_spec.rb +66 -22
 - data/spec/client/headers_spec.rb +29 -0
 - data/spec/services/middleware/middleware_assumed_identity_spec.rb +651 -0
 - data/spec/services/middleware/middleware_multi_local_spec.rb +145 -13
 - data/spec/services/middleware/middleware_multi_remote_spec.rb +145 -2
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,15 +1,15 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            !binary "U0hBMQ==":
         
     | 
| 
       3 
3 
     | 
    
         
             
              metadata.gz: !binary |-
         
     | 
| 
       4 
     | 
    
         
            -
                 
     | 
| 
      
 4 
     | 
    
         
            +
                YzEwZWNjMTA5OTJhODlhN2VkZGQxMDQ0NzNhOGVjZjUxMTM2ZmM1Nw==
         
     | 
| 
       5 
5 
     | 
    
         
             
              data.tar.gz: !binary |-
         
     | 
| 
       6 
     | 
    
         
            -
                 
     | 
| 
      
 6 
     | 
    
         
            +
                OTA1MzJjZTZlYzFhY2FiNWUxZWM3MDBiN2QwYzEwNDYyNDM2Y2ZjOA==
         
     | 
| 
       7 
7 
     | 
    
         
             
            SHA512:
         
     | 
| 
       8 
8 
     | 
    
         
             
              metadata.gz: !binary |-
         
     | 
| 
       9 
     | 
    
         
            -
                 
     | 
| 
       10 
     | 
    
         
            -
                 
     | 
| 
       11 
     | 
    
         
            -
                 
     | 
| 
      
 9 
     | 
    
         
            +
                ZDQ4YmVkYmQ3YWEwMWY1NGU1ZDZlYTA2NjAxNzM2NTFiYzk5NjI1NTNmZWE0
         
     | 
| 
      
 10 
     | 
    
         
            +
                NGYwYjhlMmIxZmY0YTViZjk4Zjg4ODgzODRjNGQ5MDhmNjEwZjVmZDJhM2Yx
         
     | 
| 
      
 11 
     | 
    
         
            +
                ODQzZjliM2NhYTE1NTQ2ZjdjNzk1YTZmNmE3NTM2MGQ2NWFhNjE=
         
     | 
| 
       12 
12 
     | 
    
         
             
              data.tar.gz: !binary |-
         
     | 
| 
       13 
     | 
    
         
            -
                 
     | 
| 
       14 
     | 
    
         
            -
                 
     | 
| 
       15 
     | 
    
         
            -
                 
     | 
| 
      
 13 
     | 
    
         
            +
                ODhiYjgzMTFmYTZhOGFhZGM4NDM2OWU3N2MwNjE3OGVhMTk0MGFkNGFhZTg5
         
     | 
| 
      
 14 
     | 
    
         
            +
                Y2E5Mzg0YjI3OTBkNzcyNjJhZGI5MjYyN2M5YTYxOWYyYjVjMTgxMGRiM2Ix
         
     | 
| 
      
 15 
     | 
    
         
            +
                MGQ4YTBiNWY4MzMzNTI3NWJkODI3ZTE0YWJmYjlkYjI3YWQ4MTg=
         
     | 
| 
         @@ -35,6 +35,29 @@ module Hoodoo 
     | 
|
| 
       35 
35 
     | 
    
         
             
                  #
         
     | 
| 
       36 
36 
     | 
    
         
             
                  UUID_HEADER_PROC = -> ( value ) { value }
         
     | 
| 
       37 
37 
     | 
    
         | 
| 
      
 38 
     | 
    
         
            +
                  # Used by HEADER_TO_PROPERTY; this Proc when called with some non-nil
         
     | 
| 
      
 39 
     | 
    
         
            +
                  # value from an HTTP header containing URL-encoded simple key/value
         
     | 
| 
      
 40 
     | 
    
         
            +
                  # pair data returns a decoded Hash of key/value pairs. Use URL encoding
         
     | 
| 
      
 41 
     | 
    
         
            +
                  # in the HTTP header value as per:
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #
         
     | 
| 
      
 43 
     | 
    
         
            +
                  # http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
         
     | 
| 
      
 44 
     | 
    
         
            +
                  #
         
     | 
| 
      
 45 
     | 
    
         
            +
                  # Invalid input will produce unusual results, e.g. an empty Hash or a
         
     | 
| 
      
 46 
     | 
    
         
            +
                  # Hash where certain keys may have empty string values.
         
     | 
| 
      
 47 
     | 
    
         
            +
                  #
         
     | 
| 
      
 48 
     | 
    
         
            +
                  KVP_PROPERTY_PROC = -> ( value ) {
         
     | 
| 
      
 49 
     | 
    
         
            +
                    Hash[ URI.decode_www_form( value ) ]
         
     | 
| 
      
 50 
     | 
    
         
            +
                  }
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  # Used by HEADER_TO_PROPERTY; this Proc when called with some non-nested
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # Hash evaluates to a URL-encoded form data String as per:
         
     | 
| 
      
 54 
     | 
    
         
            +
                  #
         
     | 
| 
      
 55 
     | 
    
         
            +
                  # http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
         
     | 
| 
      
 56 
     | 
    
         
            +
                  #
         
     | 
| 
      
 57 
     | 
    
         
            +
                  KVP_HEADER_PROC = -> ( value ) {
         
     | 
| 
      
 58 
     | 
    
         
            +
                    URI.encode_www_form( value )
         
     | 
| 
      
 59 
     | 
    
         
            +
                  }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
       38 
61 
     | 
    
         
             
                  # Used by HEADER_TO_PROPERTY; this Proc when called with some non-nil
         
     | 
| 
       39 
62 
     | 
    
         
             
                  # value from an HTTP header representing a Date/Time in a supported
         
     | 
| 
       40 
63 
     | 
    
         
             
                  # format, evaluates to either a parsed DateTime instance or +nil+ if the
         
     | 
| 
         @@ -152,6 +175,16 @@ module Hoodoo 
     | 
|
| 
       152 
175 
     | 
    
         
             
                      :secured       => true,
         
     | 
| 
       153 
176 
     | 
    
         
             
                    },
         
     | 
| 
       154 
177 
     | 
    
         | 
| 
      
 178 
     | 
    
         
            +
                    'HTTP_X_ASSUME_IDENTITY_OF' => {
         
     | 
| 
      
 179 
     | 
    
         
            +
                      :property      => :assume_identity_of,
         
     | 
| 
      
 180 
     | 
    
         
            +
                      :property_proc => KVP_PROPERTY_PROC,
         
     | 
| 
      
 181 
     | 
    
         
            +
                      :header        => 'X-Assume-Identity-Of',
         
     | 
| 
      
 182 
     | 
    
         
            +
                      :header_proc   => KVP_HEADER_PROC,
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                      :secured       => true,
         
     | 
| 
      
 185 
     | 
    
         
            +
                      :auto_transfer => true,
         
     | 
| 
      
 186 
     | 
    
         
            +
                    },
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
       155 
188 
     | 
    
         
             
                    'HTTP_X_DATED_AT' => {
         
     | 
| 
       156 
189 
     | 
    
         
             
                      :property      => :dated_at,
         
     | 
| 
       157 
190 
     | 
    
         
             
                      :property_proc => DATETIME_IN_PAST_ONLY_PROPERTY_PROC,
         
     | 
| 
         @@ -758,6 +758,10 @@ module Hoodoo; module Services 
     | 
|
| 
       758 
758 
     | 
    
         | 
| 
       759 
759 
     | 
    
         
             
                  return add_local_errors.call() if local_response.halt_processing?
         
     | 
| 
       760 
760 
     | 
    
         | 
| 
      
 761 
     | 
    
         
            +
                  deal_with_x_assume_identity_of( local_interaction )
         
     | 
| 
      
 762 
     | 
    
         
            +
             
     | 
| 
      
 763 
     | 
    
         
            +
                  return add_local_errors.call() if local_response.halt_processing?
         
     | 
| 
      
 764 
     | 
    
         
            +
             
     | 
| 
       761 
765 
     | 
    
         
             
                  # Construct the local request details.
         
     | 
| 
       762 
766 
     | 
    
         | 
| 
       763 
767 
     | 
    
         
             
                  local_request.uri_path_components = upc
         
     | 
| 
         @@ -1186,7 +1190,7 @@ module Hoodoo; module Services 
     | 
|
| 
       1186 
1190 
     | 
    
         
             
                  end
         
     | 
| 
       1187 
1191 
     | 
    
         | 
| 
       1188 
1192 
     | 
    
         
             
                  if secure == false || level == :error
         
     | 
| 
       1189 
     | 
    
         
            -
                    body =  
     | 
| 
      
 1193 
     | 
    
         
            +
                    body = String.new
         
     | 
| 
       1190 
1194 
     | 
    
         
             
                    rack_data[ 2 ].each { | thing | body << thing.to_s }
         
     | 
| 
       1191 
1195 
     | 
    
         | 
| 
       1192 
1196 
     | 
    
         
             
                    if interaction.context.response.halt_processing?
         
     | 
| 
         @@ -1547,10 +1551,13 @@ module Hoodoo; module Services 
     | 
|
| 
       1547 
1551 
     | 
    
         | 
| 
       1548 
1552 
     | 
    
         
             
                  # Load the session and then, in the context of a loaded session, process
         
     | 
| 
       1549 
1553 
     | 
    
         
             
                  # any remaining extension ("X-...") HTTP headers, checking up on secured
         
     | 
| 
       1550 
     | 
    
         
            -
                  # headers in passing.
         
     | 
| 
      
 1554 
     | 
    
         
            +
                  # headers in passing. There's special handling for X-Assume-Identity-Of,
         
     | 
| 
      
 1555 
     | 
    
         
            +
                  # which may update the session data loaded into 'interaction' with new
         
     | 
| 
      
 1556 
     | 
    
         
            +
                  # identity information.
         
     | 
| 
       1551 
1557 
     | 
    
         | 
| 
       1552 
1558 
     | 
    
         
             
                  load_session_into( interaction )
         
     | 
| 
       1553 
1559 
     | 
    
         
             
                  deal_with_x_headers( interaction )
         
     | 
| 
      
 1560 
     | 
    
         
            +
                  deal_with_x_assume_identity_of( interaction )
         
     | 
| 
       1554 
1561 
     | 
    
         | 
| 
       1555 
1562 
     | 
    
         
             
                  return nil
         
     | 
| 
       1556 
1563 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1934,6 +1941,167 @@ module Hoodoo; module Services 
     | 
|
| 
       1934 
1941 
     | 
    
         
             
                  end
         
     | 
| 
       1935 
1942 
     | 
    
         
             
                end
         
     | 
| 
       1936 
1943 
     | 
    
         | 
| 
      
 1944 
     | 
    
         
            +
                # The X-Assume-Identity-Of secured HTTP header allows a caller to specify
         
     | 
| 
      
 1945 
     | 
    
         
            +
                # values for parts of their session's "identity" section, based upon
         
     | 
| 
      
 1946 
     | 
    
         
            +
                # permitted values described in their session's "scoping" section. This
         
     | 
| 
      
 1947 
     | 
    
         
            +
                # method assumes that the permission to use the header in the first place
         
     | 
| 
      
 1948 
     | 
    
         
            +
                # has already been established by #deal_with_x_headers and, as a result,
         
     | 
| 
      
 1949 
     | 
    
         
            +
                # relevant property information has been written into the request object.
         
     | 
| 
      
 1950 
     | 
    
         
            +
                #
         
     | 
| 
      
 1951 
     | 
    
         
            +
                # The header's value is parsed and checked against the session scoping
         
     | 
| 
      
 1952 
     | 
    
         
            +
                # data. If everything looks good, the loaded session's identity is
         
     | 
| 
      
 1953 
     | 
    
         
            +
                # updated accordingly. If there are any problems, one or more errors will
         
     | 
| 
      
 1954 
     | 
    
         
            +
                # be added to the interaction's context's response object.
         
     | 
| 
      
 1955 
     | 
    
         
            +
                #
         
     | 
| 
      
 1956 
     | 
    
         
            +
                # +interaction+:: Hoodoo::Services::Middleware::Interaction instance
         
     | 
| 
      
 1957 
     | 
    
         
            +
                #                 describing the current interaction. Updated on exit.
         
     | 
| 
      
 1958 
     | 
    
         
            +
                #
         
     | 
| 
      
 1959 
     | 
    
         
            +
                def deal_with_x_assume_identity_of( interaction )
         
     | 
| 
      
 1960 
     | 
    
         
            +
             
     | 
| 
      
 1961 
     | 
    
         
            +
                  # Header not in use? Exit now.
         
     | 
| 
      
 1962 
     | 
    
         
            +
                  #
         
     | 
| 
      
 1963 
     | 
    
         
            +
                  return if interaction.context.request.assume_identity_of.nil?
         
     | 
| 
      
 1964 
     | 
    
         
            +
             
     | 
| 
      
 1965 
     | 
    
         
            +
                  input_hash = interaction.context.request.assume_identity_of
         
     | 
| 
      
 1966 
     | 
    
         
            +
                  rules_hash = interaction.context.session.scoping.authorised_identities rescue {}
         
     | 
| 
      
 1967 
     | 
    
         
            +
             
     | 
| 
      
 1968 
     | 
    
         
            +
                  if ( input_hash.empty? )
         
     | 
| 
      
 1969 
     | 
    
         
            +
                    interaction.context.response.errors.add_error(
         
     | 
| 
      
 1970 
     | 
    
         
            +
                      'generic.malformed',
         
     | 
| 
      
 1971 
     | 
    
         
            +
                      {
         
     | 
| 
      
 1972 
     | 
    
         
            +
                        :message   => "X-Assume-Identity-Of header value is malformed",
         
     | 
| 
      
 1973 
     | 
    
         
            +
                        :reference => { :header_value => ( interaction.context.request.assume_identity_of rescue 'unknown' ) }
         
     | 
| 
      
 1974 
     | 
    
         
            +
                      }
         
     | 
| 
      
 1975 
     | 
    
         
            +
                    )
         
     | 
| 
      
 1976 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1977 
     | 
    
         
            +
             
     | 
| 
      
 1978 
     | 
    
         
            +
                  return if interaction.context.response.halt_processing?
         
     | 
| 
      
 1979 
     | 
    
         
            +
             
     | 
| 
      
 1980 
     | 
    
         
            +
                  identity_overrides = validate_x_assume_identity_of( interaction, input_hash, rules_hash )
         
     | 
| 
      
 1981 
     | 
    
         
            +
             
     | 
| 
      
 1982 
     | 
    
         
            +
                  return if interaction.context.response.halt_processing?
         
     | 
| 
      
 1983 
     | 
    
         
            +
             
     | 
| 
      
 1984 
     | 
    
         
            +
                  identity_overrides.each do | key, value |
         
     | 
| 
      
 1985 
     | 
    
         
            +
                    interaction.context.session.identity.send( "#{ key }=", value )
         
     | 
| 
      
 1986 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1987 
     | 
    
         
            +
                end
         
     | 
| 
      
 1988 
     | 
    
         
            +
             
     | 
| 
      
 1989 
     | 
    
         
            +
                # Back-end to #deal_with_x_assume_identity_of which recursively processes
         
     | 
| 
      
 1990 
     | 
    
         
            +
                # a rule set against a value from the X-Assume-Identity-Of HTTP header and
         
     | 
| 
      
 1991 
     | 
    
         
            +
                # either updates the interaction's context's response object with error
         
     | 
| 
      
 1992 
     | 
    
         
            +
                # details if anything is wrong, or returns a flat Hash of keys and values
         
     | 
| 
      
 1993 
     | 
    
         
            +
                # to (over-)write in the session's identity section.
         
     | 
| 
      
 1994 
     | 
    
         
            +
                #
         
     | 
| 
      
 1995 
     | 
    
         
            +
                # +interaction+:: Hoodoo::Services::Middleware::Interaction instance
         
     | 
| 
      
 1996 
     | 
    
         
            +
                #                 describing the current interaction. Will be updated on
         
     | 
| 
      
 1997 
     | 
    
         
            +
                #                 exit if errors occur.
         
     | 
| 
      
 1998 
     | 
    
         
            +
                #
         
     | 
| 
      
 1999 
     | 
    
         
            +
                # +input_hash+::  Header value for X-Assume-Identity-Of processed into a
         
     | 
| 
      
 2000 
     | 
    
         
            +
                #                 flat Hash of String keys and String values.
         
     | 
| 
      
 2001 
     | 
    
         
            +
                #
         
     | 
| 
      
 2002 
     | 
    
         
            +
                # +rules_hash+::  Rules Hash from the session scoping data - usually its
         
     | 
| 
      
 2003 
     | 
    
         
            +
                #                 "authorised_identities" key - or a sub-hash from nested
         
     | 
| 
      
 2004 
     | 
    
         
            +
                #                 data during recursive calls.
         
     | 
| 
      
 2005 
     | 
    
         
            +
                #
         
     | 
| 
      
 2006 
     | 
    
         
            +
                # +recursive+::   Top-level callers MUST omit this parameter. Internal
         
     | 
| 
      
 2007 
     | 
    
         
            +
                #                 recursive callers MUST set this to +true+.
         
     | 
| 
      
 2008 
     | 
    
         
            +
                #
         
     | 
| 
      
 2009 
     | 
    
         
            +
                def validate_x_assume_identity_of( interaction, input_hash, rules_hash, recursive = false )
         
     | 
| 
      
 2010 
     | 
    
         
            +
                  identity_overrides = {}
         
     | 
| 
      
 2011 
     | 
    
         
            +
             
     | 
| 
      
 2012 
     | 
    
         
            +
                  unless rules_hash.is_a?( Hash )
         
     | 
| 
      
 2013 
     | 
    
         
            +
                    interaction.context.response.errors.add_error(
         
     | 
| 
      
 2014 
     | 
    
         
            +
                      'generic.malformed',
         
     | 
| 
      
 2015 
     | 
    
         
            +
                      :message => "X-Assume-Identity-Of header cannot be processed because of malformed scoping rules in Session's associated Caller",
         
     | 
| 
      
 2016 
     | 
    
         
            +
                    )
         
     | 
| 
      
 2017 
     | 
    
         
            +
             
     | 
| 
      
 2018 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 2019 
     | 
    
         
            +
                  end
         
     | 
| 
      
 2020 
     | 
    
         
            +
             
     | 
| 
      
 2021 
     | 
    
         
            +
                  rules_hash.each do | rules_key, rules_value |
         
     | 
| 
      
 2022 
     | 
    
         
            +
             
     | 
| 
      
 2023 
     | 
    
         
            +
                    next unless input_hash.has_key?( rules_key )
         
     | 
| 
      
 2024 
     | 
    
         
            +
                    input_value = input_hash[ rules_key ]
         
     | 
| 
      
 2025 
     | 
    
         
            +
             
     | 
| 
      
 2026 
     | 
    
         
            +
                    unless input_value.is_a?( String )
         
     | 
| 
      
 2027 
     | 
    
         
            +
                      raise "Internal error - internal validation input value for X-Assume-Identity-Of is not a String"
         
     | 
| 
      
 2028 
     | 
    
         
            +
                    end
         
     | 
| 
      
 2029 
     | 
    
         
            +
             
     | 
| 
      
 2030 
     | 
    
         
            +
                    if rules_value.is_a?( Array )
         
     | 
| 
      
 2031 
     | 
    
         
            +
                      if rules_value.include?( input_value )
         
     | 
| 
      
 2032 
     | 
    
         
            +
                        identity_overrides[ rules_key ] = input_value
         
     | 
| 
      
 2033 
     | 
    
         
            +
                      else
         
     | 
| 
      
 2034 
     | 
    
         
            +
                        interaction.context.response.errors.add_error(
         
     | 
| 
      
 2035 
     | 
    
         
            +
                          'platform.forbidden',
         
     | 
| 
      
 2036 
     | 
    
         
            +
                          {
         
     | 
| 
      
 2037 
     | 
    
         
            +
                            :message   => "X-Assume-Identity-Of header value requests a prohibited identity quantity",
         
     | 
| 
      
 2038 
     | 
    
         
            +
                            :reference =>
         
     | 
| 
      
 2039 
     | 
    
         
            +
                            {
         
     | 
| 
      
 2040 
     | 
    
         
            +
                              :name  => rules_key,
         
     | 
| 
      
 2041 
     | 
    
         
            +
                              :value => input_value
         
     | 
| 
      
 2042 
     | 
    
         
            +
                            }
         
     | 
| 
      
 2043 
     | 
    
         
            +
                          }
         
     | 
| 
      
 2044 
     | 
    
         
            +
                        )
         
     | 
| 
      
 2045 
     | 
    
         
            +
                        return nil
         
     | 
| 
      
 2046 
     | 
    
         
            +
                      end
         
     | 
| 
      
 2047 
     | 
    
         
            +
             
     | 
| 
      
 2048 
     | 
    
         
            +
                    elsif rules_value.is_a?( Hash )
         
     | 
| 
      
 2049 
     | 
    
         
            +
                      if rules_value.has_key?( input_value )
         
     | 
| 
      
 2050 
     | 
    
         
            +
                        identity_overrides[ rules_key ] = input_value
         
     | 
| 
      
 2051 
     | 
    
         
            +
             
     | 
| 
      
 2052 
     | 
    
         
            +
                        nested_identity_overrides = validate_x_assume_identity_of(
         
     | 
| 
      
 2053 
     | 
    
         
            +
                          interaction,
         
     | 
| 
      
 2054 
     | 
    
         
            +
                          input_hash,
         
     | 
| 
      
 2055 
     | 
    
         
            +
                          rules_value[ input_value ],
         
     | 
| 
      
 2056 
     | 
    
         
            +
                          true
         
     | 
| 
      
 2057 
     | 
    
         
            +
                        )
         
     | 
| 
      
 2058 
     | 
    
         
            +
             
     | 
| 
      
 2059 
     | 
    
         
            +
                        return if nested_identity_overrides.nil?
         
     | 
| 
      
 2060 
     | 
    
         
            +
                        identity_overrides.merge!( nested_identity_overrides )
         
     | 
| 
      
 2061 
     | 
    
         
            +
             
     | 
| 
      
 2062 
     | 
    
         
            +
                      else
         
     | 
| 
      
 2063 
     | 
    
         
            +
                        interaction.context.response.errors.add_error(
         
     | 
| 
      
 2064 
     | 
    
         
            +
                          'platform.forbidden',
         
     | 
| 
      
 2065 
     | 
    
         
            +
                          {
         
     | 
| 
      
 2066 
     | 
    
         
            +
                            :message   => "X-Assume-Identity-Of header value requests a prohibited identity quantity",
         
     | 
| 
      
 2067 
     | 
    
         
            +
                            :reference =>
         
     | 
| 
      
 2068 
     | 
    
         
            +
                            {
         
     | 
| 
      
 2069 
     | 
    
         
            +
                              :name  => rules_key,
         
     | 
| 
      
 2070 
     | 
    
         
            +
                              :value => input_value
         
     | 
| 
      
 2071 
     | 
    
         
            +
                            }
         
     | 
| 
      
 2072 
     | 
    
         
            +
                          }
         
     | 
| 
      
 2073 
     | 
    
         
            +
                        )
         
     | 
| 
      
 2074 
     | 
    
         
            +
                        return nil
         
     | 
| 
      
 2075 
     | 
    
         
            +
             
     | 
| 
      
 2076 
     | 
    
         
            +
                      end
         
     | 
| 
      
 2077 
     | 
    
         
            +
             
     | 
| 
      
 2078 
     | 
    
         
            +
                    else
         
     | 
| 
      
 2079 
     | 
    
         
            +
                      interaction.context.response.errors.add_error(
         
     | 
| 
      
 2080 
     | 
    
         
            +
                        'generic.malformed',
         
     | 
| 
      
 2081 
     | 
    
         
            +
                        :message => "X-Assume-Identity-Of header cannot be processed because of malformed scoping rules in Session's associated Caller",
         
     | 
| 
      
 2082 
     | 
    
         
            +
                      )
         
     | 
| 
      
 2083 
     | 
    
         
            +
                      return nil
         
     | 
| 
      
 2084 
     | 
    
         
            +
             
     | 
| 
      
 2085 
     | 
    
         
            +
                    end
         
     | 
| 
      
 2086 
     | 
    
         
            +
                  end
         
     | 
| 
      
 2087 
     | 
    
         
            +
             
     | 
| 
      
 2088 
     | 
    
         
            +
                  unless recursive || ( input_hash.keys - identity_overrides.keys ).empty?
         
     | 
| 
      
 2089 
     | 
    
         
            +
                    interaction.context.response.errors.add_error(
         
     | 
| 
      
 2090 
     | 
    
         
            +
                      'platform.forbidden',
         
     | 
| 
      
 2091 
     | 
    
         
            +
                      {
         
     | 
| 
      
 2092 
     | 
    
         
            +
                        :message   => "X-Assume-Identity-Of header value requests prohibited identity name(s)",
         
     | 
| 
      
 2093 
     | 
    
         
            +
                        :reference =>
         
     | 
| 
      
 2094 
     | 
    
         
            +
                        {
         
     | 
| 
      
 2095 
     | 
    
         
            +
                          :names => ( input_hash.keys - identity_overrides.keys ).sort().join( ',' )
         
     | 
| 
      
 2096 
     | 
    
         
            +
                        }
         
     | 
| 
      
 2097 
     | 
    
         
            +
                      }
         
     | 
| 
      
 2098 
     | 
    
         
            +
                    )
         
     | 
| 
      
 2099 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 2100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 2101 
     | 
    
         
            +
             
     | 
| 
      
 2102 
     | 
    
         
            +
                  return identity_overrides
         
     | 
| 
      
 2103 
     | 
    
         
            +
                end
         
     | 
| 
      
 2104 
     | 
    
         
            +
             
     | 
| 
       1937 
2105 
     | 
    
         
             
                # Preprocessing stage that sets up common headers required in any response.
         
     | 
| 
       1938 
2106 
     | 
    
         
             
                # May vary according to inbound content type requested. If processing was
         
     | 
| 
       1939 
2107 
     | 
    
         
             
                # aborted early (e.g. missing inbound Content-Type) we may fall to defaults.
         
     | 
| 
         @@ -1941,7 +2109,8 @@ module Hoodoo; module Services 
     | 
|
| 
       1941 
2109 
     | 
    
         
             
                # (At the time of writing, platform documentations say we're JSON only - but
         
     | 
| 
       1942 
2110 
     | 
    
         
             
                # there's an strong chance of e.g. XML representation being demanded later).
         
     | 
| 
       1943 
2111 
     | 
    
         
             
                #
         
     | 
| 
       1944 
     | 
    
         
            -
                # + 
     | 
| 
      
 2112 
     | 
    
         
            +
                # +interaction+:: Hoodoo::Services::Middleware::Interaction instance
         
     | 
| 
      
 2113 
     | 
    
         
            +
                #                 describing the current interaction. Updated on exit.
         
     | 
| 
       1945 
2114 
     | 
    
         
             
                #
         
     | 
| 
       1946 
2115 
     | 
    
         
             
                def set_common_response_headers( interaction )
         
     | 
| 
       1947 
2116 
     | 
    
         
             
                  interaction.context.response.add_header( 'X-Interaction-ID', interaction.interaction_id )
         
     | 
    
        data/lib/hoodoo/version.rb
    CHANGED
    
    
    
        data/spec/client/client_spec.rb
    CHANGED
    
    | 
         @@ -146,20 +146,22 @@ class RSpecClientTestTargetImplementation < Hoodoo::Services::Implementation 
     | 
|
| 
       146 
146 
     | 
    
         
             
                  # if adding things.
         
     | 
| 
       147 
147 
     | 
    
         | 
| 
       148 
148 
     | 
    
         
             
                  {
         
     | 
| 
       149 
     | 
    
         
            -
                    'id' 
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
       153 
     | 
    
         
            -
                    'created_at' 
     | 
| 
       154 
     | 
    
         
            -
                    'kind' 
     | 
| 
       155 
     | 
    
         
            -
                    'language' 
     | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
       157 
     | 
    
         
            -
                    'embeds' 
     | 
| 
       158 
     | 
    
         
            -
                    'body_hash' 
     | 
| 
       159 
     | 
    
         
            -
                    'dated_at' 
     | 
| 
       160 
     | 
    
         
            -
                    'dated_from' 
     | 
| 
       161 
     | 
    
         
            -
                    'resource_uuid' 
     | 
| 
       162 
     | 
    
         
            -
                    'deja_vu' 
     | 
| 
      
 149 
     | 
    
         
            +
                    'id'                 => context.request.ident                 ||
         
     | 
| 
      
 150 
     | 
    
         
            +
                                            context.request.body.try( :[], 'id' ) ||
         
     | 
| 
      
 151 
     | 
    
         
            +
                                            Hoodoo::UUID.generate(),
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                    'created_at'         => Time.now.utc.iso8601,
         
     | 
| 
      
 154 
     | 
    
         
            +
                    'kind'               => 'RSpecClientTestTarget',
         
     | 
| 
      
 155 
     | 
    
         
            +
                    'language'           => context.request.locale,
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                    'embeds'             => context.request.embeds,
         
     | 
| 
      
 158 
     | 
    
         
            +
                    'body_hash'          => context.request.body,
         
     | 
| 
      
 159 
     | 
    
         
            +
                    'dated_at'           => context.request.dated_at.nil?   ? nil : Hoodoo::Utilities.nanosecond_iso8601( context.request.dated_at   ),
         
     | 
| 
      
 160 
     | 
    
         
            +
                    'dated_from'         => context.request.dated_from.nil? ? nil : Hoodoo::Utilities.nanosecond_iso8601( context.request.dated_from ),
         
     | 
| 
      
 161 
     | 
    
         
            +
                    'resource_uuid'      => context.request.resource_uuid,
         
     | 
| 
      
 162 
     | 
    
         
            +
                    'deja_vu'            => context.request.deja_vu,
         
     | 
| 
      
 163 
     | 
    
         
            +
                    'assume_identity_of' => context.request.assume_identity_of,
         
     | 
| 
      
 164 
     | 
    
         
            +
                    'actual_identity'    => ( context.session.identity.to_h rescue nil ),
         
     | 
| 
       163 
165 
     | 
    
         
             
                  }
         
     | 
| 
       164 
166 
     | 
    
         
             
                end
         
     | 
| 
       165 
167 
     | 
    
         
             
            end
         
     | 
| 
         @@ -213,6 +215,8 @@ describe Hoodoo::Client do 
     | 
|
| 
       213 
215 
     | 
    
         
             
                @old_test_session = Hoodoo::Services::Middleware.test_session()
         
     | 
| 
       214 
216 
     | 
    
         
             
                @port = spec_helper_start_svc_app_in_thread_for( RSpecClientTestService )
         
     | 
| 
       215 
217 
     | 
    
         
             
                @https_port = spec_helper_start_svc_app_in_thread_for( RSpecClientTestService, true )
         
     | 
| 
      
 218 
     | 
    
         
            +
                @authorised_identities = { 'member_id' => [ '23', '24' ] }
         
     | 
| 
      
 219 
     | 
    
         
            +
                @example_authorised_identity = { 'member_id' => '23' }
         
     | 
| 
       216 
220 
     | 
    
         
             
              end
         
     | 
| 
       217 
221 
     | 
    
         | 
| 
       218 
222 
     | 
    
         
             
              after :all do
         
     | 
| 
         @@ -249,15 +253,17 @@ describe Hoodoo::Client do 
     | 
|
| 
       249 
253 
     | 
    
         
             
                # "def option_based_expectations" later in this file. Be careful
         
     | 
| 
       250 
254 
     | 
    
         
             
                # to follow the naming convention evident below if adding things.
         
     | 
| 
       251 
255 
     | 
    
         | 
| 
       252 
     | 
    
         
            -
                @expected_dated_at 
     | 
| 
       253 
     | 
    
         
            -
                @expected_dated_from 
     | 
| 
       254 
     | 
    
         
            -
                @expected_resource_uuid 
     | 
| 
       255 
     | 
    
         
            -
                @ 
     | 
| 
      
 256 
     | 
    
         
            +
                @expected_dated_at           = @dated_at.nil?   ? nil : Hoodoo::Utilities.nanosecond_iso8601( @dated_at   )
         
     | 
| 
      
 257 
     | 
    
         
            +
                @expected_dated_from         = @dated_from.nil? ? nil : Hoodoo::Utilities.nanosecond_iso8601( @dated_from )
         
     | 
| 
      
 258 
     | 
    
         
            +
                @expected_resource_uuid      = @resource_uuid
         
     | 
| 
      
 259 
     | 
    
         
            +
                @expected_assume_identity_of = @assume_identity_of
         
     | 
| 
      
 260 
     | 
    
         
            +
                @expected_deja_vu            = @deja_vu != true ? nil : true
         
     | 
| 
       256 
261 
     | 
    
         | 
| 
       257 
     | 
    
         
            -
                endpoint_opts[ :dated_at 
     | 
| 
       258 
     | 
    
         
            -
                endpoint_opts[ :dated_from 
     | 
| 
       259 
     | 
    
         
            -
                endpoint_opts[ :resource_uuid 
     | 
| 
       260 
     | 
    
         
            -
                endpoint_opts[ : 
     | 
| 
      
 262 
     | 
    
         
            +
                endpoint_opts[ :dated_at           ] = @dated_at           unless @dated_at.nil?
         
     | 
| 
      
 263 
     | 
    
         
            +
                endpoint_opts[ :dated_from         ] = @dated_from         unless @dated_from.nil?
         
     | 
| 
      
 264 
     | 
    
         
            +
                endpoint_opts[ :resource_uuid      ] = @resource_uuid      unless @resource_uuid.nil?
         
     | 
| 
      
 265 
     | 
    
         
            +
                endpoint_opts[ :assume_identity_of ] = @assume_identity_of unless @assume_identity_of.nil?
         
     | 
| 
      
 266 
     | 
    
         
            +
                endpoint_opts[ :deja_vu            ] = @deja_vu            if     @deja_vu == true
         
     | 
| 
       261 
267 
     | 
    
         | 
| 
       262 
268 
     | 
    
         
             
                if rand( 2 ) == 0
         
     | 
| 
       263 
269 
     | 
    
         
             
                  override_locale          = SecureRandom.urlsafe_base64( 2 )
         
     | 
| 
         @@ -508,6 +514,8 @@ describe Hoodoo::Client do 
     | 
|
| 
       508 
514 
     | 
    
         
             
                      case property
         
     | 
| 
       509 
515 
     | 
    
         
             
                        when :resource_uuid
         
     | 
| 
       510 
516 
     | 
    
         
             
                          @resource_uuid = Hoodoo::UUID.generate
         
     | 
| 
      
 517 
     | 
    
         
            +
                        when :assume_identity_of
         
     | 
| 
      
 518 
     | 
    
         
            +
                          @assume_identity_of = @example_authorised_identity
         
     | 
| 
       511 
519 
     | 
    
         
             
                        else
         
     | 
| 
       512 
520 
     | 
    
         
             
                          raise "Update client_spec.rb with new secured properties for test"
         
     | 
| 
       513 
521 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -725,8 +733,10 @@ describe Hoodoo::Client do 
     | 
|
| 
       725 
733 
     | 
    
         
             
                context 'and with secured option' do
         
     | 
| 
       726 
734 
     | 
    
         
             
                  before :each do
         
     | 
| 
       727 
735 
     | 
    
         
             
                    test_session = @old_test_session.dup
         
     | 
| 
      
 736 
     | 
    
         
            +
                    test_session.identity = OpenStruct.new
         
     | 
| 
       728 
737 
     | 
    
         
             
                    test_session.scoping = @old_test_session.scoping.dup
         
     | 
| 
       729 
738 
     | 
    
         
             
                    test_session.scoping.authorised_http_headers = []
         
     | 
| 
      
 739 
     | 
    
         
            +
                    test_session.scoping.authorised_identities = @authorised_identities
         
     | 
| 
       730 
740 
     | 
    
         | 
| 
       731 
741 
     | 
    
         
             
                    Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
         
     | 
| 
       732 
742 
     | 
    
         
             
                      next unless description[ :secured ] == true
         
     | 
| 
         @@ -750,6 +760,8 @@ describe Hoodoo::Client do 
     | 
|
| 
       750 
760 
     | 
    
         
             
                      case property
         
     | 
| 
       751 
761 
     | 
    
         
             
                        when :resource_uuid
         
     | 
| 
       752 
762 
     | 
    
         
             
                          @resource_uuid = Hoodoo::UUID.generate
         
     | 
| 
      
 763 
     | 
    
         
            +
                        when :assume_identity_of
         
     | 
| 
      
 764 
     | 
    
         
            +
                          @assume_identity_of = @example_authorised_identity
         
     | 
| 
       753 
765 
     | 
    
         
             
                        else
         
     | 
| 
       754 
766 
     | 
    
         
             
                          raise "Update client_spec.rb with new secured properties for test"
         
     | 
| 
       755 
767 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -763,6 +775,8 @@ describe Hoodoo::Client do 
     | 
|
| 
       763 
775 
     | 
    
         
             
                      result     = @endpoint.show( mock_ident )
         
     | 
| 
       764 
776 
     | 
    
         | 
| 
       765 
777 
     | 
    
         
             
                      expect( result.platform_errors.has_errors? ).to eq( false )
         
     | 
| 
      
 778 
     | 
    
         
            +
             
     | 
| 
      
 779 
     | 
    
         
            +
                      option_based_expectations( result )
         
     | 
| 
       766 
780 
     | 
    
         
             
                    end
         
     | 
| 
       767 
781 
     | 
    
         
             
                  end
         
     | 
| 
       768 
782 
     | 
    
         | 
| 
         @@ -781,6 +795,36 @@ describe Hoodoo::Client do 
     | 
|
| 
       781 
795 
     | 
    
         
             
                    expect( result.platform_errors.has_errors? ).to eq( false )
         
     | 
| 
       782 
796 
     | 
    
         
             
                    expect( result[ 'id' ] ).to eq( @resource_uuid )
         
     | 
| 
       783 
797 
     | 
    
         
             
                  end
         
     | 
| 
      
 798 
     | 
    
         
            +
             
     | 
| 
      
 799 
     | 
    
         
            +
                  context "'assume_identity_of' in use" do
         
     | 
| 
      
 800 
     | 
    
         
            +
                    it 'but invalid' do
         
     | 
| 
      
 801 
     | 
    
         
            +
                      @assume_identity_of = { 'invalid' => 'Hoodoo::UUID.generate' }
         
     | 
| 
      
 802 
     | 
    
         
            +
             
     | 
| 
      
 803 
     | 
    
         
            +
                      set_vars_for(
         
     | 
| 
      
 804 
     | 
    
         
            +
                        base_uri:     "http://localhost:#{ @port }",
         
     | 
| 
      
 805 
     | 
    
         
            +
                        auto_session: false
         
     | 
| 
      
 806 
     | 
    
         
            +
                      )
         
     | 
| 
      
 807 
     | 
    
         
            +
             
     | 
| 
      
 808 
     | 
    
         
            +
                      result = @endpoint.create( { 'hello' => 'world' } )
         
     | 
| 
      
 809 
     | 
    
         
            +
             
     | 
| 
      
 810 
     | 
    
         
            +
                      expect( result.platform_errors.has_errors? ).to eq( true )
         
     | 
| 
      
 811 
     | 
    
         
            +
                      expect( result.platform_errors.errors[ 0 ][ 'code' ] ).to eq( 'platform.forbidden' )
         
     | 
| 
      
 812 
     | 
    
         
            +
                    end
         
     | 
| 
      
 813 
     | 
    
         
            +
             
     | 
| 
      
 814 
     | 
    
         
            +
                    it 'and valid' do
         
     | 
| 
      
 815 
     | 
    
         
            +
                      @assume_identity_of = @example_authorised_identity
         
     | 
| 
      
 816 
     | 
    
         
            +
             
     | 
| 
      
 817 
     | 
    
         
            +
                      set_vars_for(
         
     | 
| 
      
 818 
     | 
    
         
            +
                        base_uri:     "http://localhost:#{ @port }",
         
     | 
| 
      
 819 
     | 
    
         
            +
                        auto_session: false
         
     | 
| 
      
 820 
     | 
    
         
            +
                      )
         
     | 
| 
      
 821 
     | 
    
         
            +
             
     | 
| 
      
 822 
     | 
    
         
            +
                      result = @endpoint.create( { 'hello' => 'world' } )
         
     | 
| 
      
 823 
     | 
    
         
            +
             
     | 
| 
      
 824 
     | 
    
         
            +
                      expect( result.platform_errors.has_errors? ).to eq( false )
         
     | 
| 
      
 825 
     | 
    
         
            +
                      expect( result[ 'actual_identity' ] ).to eq( @example_authorised_identity )
         
     | 
| 
      
 826 
     | 
    
         
            +
                    end
         
     | 
| 
      
 827 
     | 
    
         
            +
                  end
         
     | 
| 
       784 
828 
     | 
    
         
             
                end
         
     | 
| 
       785 
829 
     | 
    
         
             
              end
         
     | 
| 
       786 
830 
     | 
    
         | 
    
        data/spec/client/headers_spec.rb
    CHANGED
    
    | 
         @@ -23,6 +23,35 @@ describe Hoodoo::Client::Headers do 
     | 
|
| 
       23 
23 
     | 
    
         
             
                end
         
     | 
| 
       24 
24 
     | 
    
         
             
              end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
      
 26 
     | 
    
         
            +
              context 'for URL encoded data' do
         
     | 
| 
      
 27 
     | 
    
         
            +
                before :each do
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @test_hash =
         
     | 
| 
      
 29 
     | 
    
         
            +
                  {
         
     | 
| 
      
 30 
     | 
    
         
            +
                    'foo' => "hello, world; this & that = foo! \r\t",
         
     | 
| 
      
 31 
     | 
    
         
            +
                    'bar' => "foo;bar=baz & this + UTF-8 / emoji 😀"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  }
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  @test_string = URI::encode_www_form( @test_hash )
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                context 'KVP_PROPERTY_PROC' do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  it 'converts valid values' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                    expect( described_class::KVP_PROPERTY_PROC.call( @test_string ) ).to eq( @test_hash )
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  it 'does not raise exceptions for invalid values' do
         
     | 
| 
      
 43 
     | 
    
         
            +
                    expect( described_class::KVP_PROPERTY_PROC.call( ''      ) ).to eq( {} )
         
     | 
| 
      
 44 
     | 
    
         
            +
                    expect( described_class::KVP_PROPERTY_PROC.call( 'hello' ) ).to eq( { 'hello' => '' } )
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                context 'KVP_HEADER_PROC' do
         
     | 
| 
      
 49 
     | 
    
         
            +
                  it 'converts values' do
         
     | 
| 
      
 50 
     | 
    
         
            +
                    expect( described_class::KVP_HEADER_PROC.call( @test_hash ) ).to eq( @test_string )
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
       26 
55 
     | 
    
         
             
              context 'DATETIME_IN_PAST_ONLY_PROPERTY_PROC' do
         
     | 
| 
       27 
56 
     | 
    
         
             
                it 'converts valid values' do
         
     | 
| 
       28 
57 
     | 
    
         
             
                  date_time = DateTime.now - 10.seconds
         
     |