haveapi 0.20.0 → 0.21.1
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 +4 -4
- data/Gemfile +1 -1
- data/Rakefile +6 -6
- data/haveapi.gemspec +13 -13
- data/lib/haveapi/action.rb +153 -167
- data/lib/haveapi/action_state.rb +2 -6
- data/lib/haveapi/actions/default.rb +8 -10
- data/lib/haveapi/api.rb +2 -1
- data/lib/haveapi/authentication/base.rb +5 -8
- data/lib/haveapi/authentication/basic/provider.rb +4 -5
- data/lib/haveapi/authentication/chain.rb +19 -17
- data/lib/haveapi/authentication/oauth2/config.rb +12 -32
- data/lib/haveapi/authentication/oauth2/provider.rb +20 -30
- data/lib/haveapi/authentication/oauth2/revoke_endpoint.rb +1 -2
- data/lib/haveapi/authentication/token/action_config.rb +5 -3
- data/lib/haveapi/authentication/token/config.rb +5 -5
- data/lib/haveapi/authentication/token/provider.rb +33 -37
- data/lib/haveapi/authorization.rb +10 -4
- data/lib/haveapi/client_example.rb +11 -14
- data/lib/haveapi/client_examples/curl.rb +37 -37
- data/lib/haveapi/client_examples/fs_client.rb +29 -31
- data/lib/haveapi/client_examples/http.rb +35 -36
- data/lib/haveapi/client_examples/js_client.rb +62 -63
- data/lib/haveapi/client_examples/php_client.rb +77 -76
- data/lib/haveapi/client_examples/ruby_cli.rb +30 -30
- data/lib/haveapi/client_examples/ruby_client.rb +26 -26
- data/lib/haveapi/common.rb +3 -4
- data/lib/haveapi/context.rb +11 -10
- data/lib/haveapi/example.rb +9 -4
- data/lib/haveapi/example_list.rb +2 -2
- data/lib/haveapi/exceptions.rb +1 -1
- data/lib/haveapi/extensions/action_exceptions.rb +2 -2
- data/lib/haveapi/extensions/base.rb +1 -3
- data/lib/haveapi/extensions/exception_mailer.rb +260 -257
- data/lib/haveapi/hooks.rb +40 -39
- data/lib/haveapi/metadata.rb +1 -1
- data/lib/haveapi/model_adapter.rb +16 -27
- data/lib/haveapi/model_adapters/active_record.rb +59 -69
- data/lib/haveapi/output_formatter.rb +7 -7
- data/lib/haveapi/output_formatters/base.rb +2 -4
- data/lib/haveapi/parameters/resource.rb +7 -7
- data/lib/haveapi/parameters/typed.rb +6 -9
- data/lib/haveapi/params.rb +38 -45
- data/lib/haveapi/resource.rb +8 -8
- data/lib/haveapi/resources/action_state.rb +11 -19
- data/lib/haveapi/server.rb +102 -107
- data/lib/haveapi/spec/api_response.rb +1 -1
- data/lib/haveapi/spec/helpers.rb +1 -1
- data/lib/haveapi/spec/mock_action.rb +11 -10
- data/lib/haveapi/spec/spec_methods.rb +9 -8
- data/lib/haveapi/tasks/yard.rb +2 -2
- data/lib/haveapi/types.rb +0 -3
- data/lib/haveapi/validator.rb +6 -3
- data/lib/haveapi/validator_chain.rb +9 -8
- data/lib/haveapi/validators/acceptance.rb +6 -6
- data/lib/haveapi/validators/confirmation.rb +2 -3
- data/lib/haveapi/validators/exclusion.rb +1 -1
- data/lib/haveapi/validators/format.rb +1 -1
- data/lib/haveapi/validators/inclusion.rb +1 -1
- data/lib/haveapi/validators/length.rb +12 -11
- data/lib/haveapi/validators/numericality.rb +14 -13
- data/lib/haveapi/validators/presence.rb +4 -3
- data/lib/haveapi/version.rb +2 -2
- data/lib/haveapi.rb +2 -3
- data/spec/.rubocop.yml +4 -0
- data/spec/action/dsl_spec.rb +18 -18
- data/spec/authorization_spec.rb +8 -8
- data/spec/common_spec.rb +2 -1
- data/spec/documentation_spec.rb +2 -9
- data/spec/envelope_spec.rb +2 -2
- data/spec/hooks_spec.rb +12 -12
- data/spec/parameters/typed_spec.rb +6 -6
- data/spec/params_spec.rb +22 -24
- data/spec/resource_spec.rb +5 -7
- data/spec/spec_helper.rb +0 -1
- data/spec/validators/acceptance_spec.rb +1 -1
- data/spec/validators/confirmation_spec.rb +5 -5
- data/spec/validators/exclusion_spec.rb +3 -3
- data/spec/validators/format_spec.rb +2 -2
- data/spec/validators/inclusion_spec.rb +4 -4
- data/spec/validators/length_spec.rb +23 -23
- data/spec/validators/numericality_spec.rb +13 -13
- data/spec/validators/presence_spec.rb +3 -3
- metadata +49 -48
| @@ -7,77 +7,77 @@ module HaveAPI::ClientExamples | |
| 7 7 | 
             
                order 20
         | 
| 8 8 |  | 
| 9 9 | 
             
                def init
         | 
| 10 | 
            -
                   | 
| 11 | 
            -
            $api = new \\HaveAPI\\Client("#{base_url}", "#{version}");
         | 
| 12 | 
            -
            END
         | 
| 10 | 
            +
                  <<~END
         | 
| 11 | 
            +
                    $api = new \\HaveAPI\\Client("#{base_url}", "#{version}");
         | 
| 12 | 
            +
                  END
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 15 | 
             
                def auth(method, desc)
         | 
| 16 16 | 
             
                  case method
         | 
| 17 17 | 
             
                  when :basic
         | 
| 18 | 
            -
                     | 
| 19 | 
            -
            #{init}
         | 
| 18 | 
            +
                    <<~END
         | 
| 19 | 
            +
                      #{init}
         | 
| 20 20 |  | 
| 21 | 
            -
            $api->authenticate("basic", ["user" => "user", "password" => "secret"]);
         | 
| 22 | 
            -
            END
         | 
| 21 | 
            +
                      $api->authenticate("basic", ["user" => "user", "password" => "secret"]);
         | 
| 22 | 
            +
                    END
         | 
| 23 23 |  | 
| 24 24 | 
             
                  when :token
         | 
| 25 | 
            -
                     | 
| 26 | 
            -
            #{init}
         | 
| 25 | 
            +
                    <<~END
         | 
| 26 | 
            +
                      #{init}
         | 
| 27 27 |  | 
| 28 | 
            -
            // Get token using username and password
         | 
| 29 | 
            -
            $api->authenticate("token", [#{auth_token_credentials(desc).map { |k, v| "\"#{k}\" => \"#{v}\"" }.join(', ')}]);
         | 
| 28 | 
            +
                      // Get token using username and password
         | 
| 29 | 
            +
                      $api->authenticate("token", [#{auth_token_credentials(desc).map { |k, v| "\"#{k}\" => \"#{v}\"" }.join(', ')}]);
         | 
| 30 30 |  | 
| 31 | 
            -
            echo "Token = ".$api->getAuthenticationProvider()->getToken();
         | 
| 31 | 
            +
                      echo "Token = ".$api->getAuthenticationProvider()->getToken();
         | 
| 32 32 |  | 
| 33 | 
            -
            // Next time, the client can authenticate using the token directly
         | 
| 34 | 
            -
            $api->authenticate("token", ["token" => $savedToken]);
         | 
| 35 | 
            -
            END
         | 
| 33 | 
            +
                      // Next time, the client can authenticate using the token directly
         | 
| 34 | 
            +
                      $api->authenticate("token", ["token" => $savedToken]);
         | 
| 35 | 
            +
                    END
         | 
| 36 36 |  | 
| 37 37 | 
             
                  when :oauth2
         | 
| 38 | 
            -
                     | 
| 39 | 
            -
            // OAuth2 requires session
         | 
| 40 | 
            -
            session_start();
         | 
| 41 | 
            -
             | 
| 42 | 
            -
            // Client instance
         | 
| 43 | 
            -
            #{init}
         | 
| 44 | 
            -
            // Check if we already have an access token
         | 
| 45 | 
            -
            if (isset($_SESSION["access_token"])) {
         | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
            } else {
         | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
            }
         | 
| 80 | 
            -
            END
         | 
| 38 | 
            +
                    <<~END
         | 
| 39 | 
            +
                      // OAuth2 requires session
         | 
| 40 | 
            +
                      session_start();
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                      // Client instance
         | 
| 43 | 
            +
                      #{init}
         | 
| 44 | 
            +
                      // Check if we already have an access token
         | 
| 45 | 
            +
                      if (isset($_SESSION["access_token"])) {
         | 
| 46 | 
            +
                        // We're already authenticated, reuse the existing access token
         | 
| 47 | 
            +
                        $api->authenticate("oauth2", ["access_token" => $_SESSION["access_token"]]);
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                      } else {
         | 
| 50 | 
            +
                        // Follow the OAuth2 authorization process to get an access token using
         | 
| 51 | 
            +
                        // authorization code
         | 
| 52 | 
            +
                        $api->authenticate("oauth2", [
         | 
| 53 | 
            +
                          // Client id and secret are given by the API server
         | 
| 54 | 
            +
                          "client_id" => "your client id",
         | 
| 55 | 
            +
                          "client_secret" => "your client secret",
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                          // This example code should run on the URL below
         | 
| 58 | 
            +
                          "redirect_uri" => "https://your-client.tld/oauth2-callback",
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                          // Scopes are specific to the API implementation
         | 
| 61 | 
            +
                          "scope" => "all",
         | 
| 62 | 
            +
                        ]);
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                        $provider = $api->getAuthenticationProvider();
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                        // We don't have authorization code yet, request one
         | 
| 67 | 
            +
                        if (!isset($_GET['code'])) {
         | 
| 68 | 
            +
                          // Redirect the user to the authorization endpoint
         | 
| 69 | 
            +
                          $provider->requestAuthorizationCode();
         | 
| 70 | 
            +
                          exit;
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                        } else {
         | 
| 73 | 
            +
                          // Request access token using the token endpoint
         | 
| 74 | 
            +
                          $provider->requestAccessToken();
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                          // Store the access token in the session
         | 
| 77 | 
            +
                          $_SESSION['access_token'] = $provider->jsonSerialize();
         | 
| 78 | 
            +
                        }
         | 
| 79 | 
            +
                      }
         | 
| 80 | 
            +
                    END
         | 
| 81 81 | 
             
                  end
         | 
| 82 82 | 
             
                end
         | 
| 83 83 |  | 
| @@ -96,7 +96,7 @@ END | |
| 96 96 |  | 
| 97 97 | 
             
                  return (out << response(sample)) if sample[:status]
         | 
| 98 98 |  | 
| 99 | 
            -
                  out <<  | 
| 99 | 
            +
                  out << '// Throws exception \\HaveAPI\\Client\\Exception\\ActionFailed'
         | 
| 100 100 | 
             
                  out
         | 
| 101 101 | 
             
                end
         | 
| 102 102 |  | 
| @@ -107,7 +107,7 @@ END | |
| 107 107 | 
             
                  when :hash
         | 
| 108 108 | 
             
                    out << "// $reply is an instance of \\HaveAPI\\Client\\Response\n"
         | 
| 109 109 | 
             
                    out << "// $reply->getResponse() returns an associative array of output parameters:\n"
         | 
| 110 | 
            -
                    out << format_parameters(:output, sample[:response] || {},  | 
| 110 | 
            +
                    out << format_parameters(:output, sample[:response] || {}, '// ')
         | 
| 111 111 |  | 
| 112 112 | 
             
                  when :hash_list
         | 
| 113 113 | 
             
                    out << "// $reply is an instance of \\HaveAPI\\Client\\Response\n"
         | 
| @@ -116,31 +116,31 @@ END | |
| 116 116 | 
             
                  when :object
         | 
| 117 117 | 
             
                    out << "// $reply is an instance of \\HaveAPI\\Client\\ResourceInstance\n"
         | 
| 118 118 |  | 
| 119 | 
            -
                    (sample[:response] || {}).each do | | 
| 120 | 
            -
                      param = action[:output][:parameters][ | 
| 119 | 
            +
                    (sample[:response] || {}).each do |pn, pv|
         | 
| 120 | 
            +
                      param = action[:output][:parameters][pn]
         | 
| 121 121 |  | 
| 122 122 | 
             
                      if param[:type] == 'Resource'
         | 
| 123 | 
            -
                        out << "// $reply->#{ | 
| 123 | 
            +
                        out << "// $reply->#{pn} = \\HaveAPI\\Client\\ResourceInstance("
         | 
| 124 124 | 
             
                        out << "resource: #{param[:resource].join('.')}, "
         | 
| 125 125 |  | 
| 126 | 
            -
                        if  | 
| 127 | 
            -
             | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 126 | 
            +
                        out << if pv.is_a?(::Hash)
         | 
| 127 | 
            +
                                 pv.map { |k, v| "#{k}: #{PP.pp(v, '').strip}" }.join(', ')
         | 
| 128 | 
            +
                               else
         | 
| 129 | 
            +
                                 "id: #{pv}"
         | 
| 130 | 
            +
                               end
         | 
| 131 131 |  | 
| 132 132 | 
             
                        out << ")\n"
         | 
| 133 133 |  | 
| 134 134 | 
             
                      elsif param[:type] == 'Custom'
         | 
| 135 | 
            -
                        out << "// $reply->#{ | 
| 135 | 
            +
                        out << "// $reply->#{pn} is a custom type"
         | 
| 136 136 |  | 
| 137 137 | 
             
                      else
         | 
| 138 | 
            -
                        out << "// $reply->#{ | 
| 138 | 
            +
                        out << "// $reply->#{pn} = #{PP.pp(pv, '')}"
         | 
| 139 139 | 
             
                      end
         | 
| 140 140 | 
             
                    end
         | 
| 141 141 |  | 
| 142 142 | 
             
                  when :object_list
         | 
| 143 | 
            -
                    out <<  | 
| 143 | 
            +
                    out << '// $reply is an instance of \\HaveAPI\\Client\\ResourceInstanceList'
         | 
| 144 144 | 
             
                  end
         | 
| 145 145 |  | 
| 146 146 | 
             
                  out
         | 
| @@ -150,12 +150,12 @@ END | |
| 150 150 | 
             
                  ret = []
         | 
| 151 151 |  | 
| 152 152 | 
             
                  params.each do |k, v|
         | 
| 153 | 
            -
                    if action[dir][:parameters][k][:type] == 'Custom'
         | 
| 154 | 
            -
             | 
| 153 | 
            +
                    ret << if action[dir][:parameters][k][:type] == 'Custom'
         | 
| 154 | 
            +
                             "#{prefix}  \"#{k}\" => custom type}"
         | 
| 155 155 |  | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 156 | 
            +
                           else
         | 
| 157 | 
            +
                             "#{prefix}  \"#{k}\" => #{value(v)}"
         | 
| 158 | 
            +
                           end
         | 
| 159 159 | 
             
                  end
         | 
| 160 160 |  | 
| 161 161 | 
             
                  "#{prefix}[\n#{ret.join(",\n")}\n#{prefix}]"
         | 
| @@ -163,6 +163,7 @@ END | |
| 163 163 |  | 
| 164 164 | 
             
                def value(v)
         | 
| 165 165 | 
             
                  return v if v.is_a?(::Numeric) || v === true || v === false
         | 
| 166 | 
            +
             | 
| 166 167 | 
             
                  "\"#{v}\""
         | 
| 167 168 | 
             
                end
         | 
| 168 169 | 
             
              end
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            module HaveAPI
         | 
| 2 | 
            -
              module CLI | 
| 2 | 
            +
              module CLI; end
         | 
| 3 3 | 
             
            end
         | 
| 4 4 |  | 
| 5 5 | 
             
            require 'haveapi/cli/output_formatter'
         | 
| @@ -18,28 +18,28 @@ module HaveAPI::ClientExamples | |
| 18 18 | 
             
                def auth(method, desc)
         | 
| 19 19 | 
             
                  case method
         | 
| 20 20 | 
             
                  when :basic
         | 
| 21 | 
            -
                     | 
| 22 | 
            -
            # Provide credentials on command line
         | 
| 23 | 
            -
            #{init} --auth basic --user user --password secret
         | 
| 21 | 
            +
                    <<~END
         | 
| 22 | 
            +
                      # Provide credentials on command line
         | 
| 23 | 
            +
                      #{init} --auth basic --user user --password secret
         | 
| 24 24 |  | 
| 25 | 
            -
            # If username or password isn't provided, the user is asked on stdin
         | 
| 26 | 
            -
            #{init} --auth basic --user user
         | 
| 27 | 
            -
            Password: secret
         | 
| 28 | 
            -
            END
         | 
| 25 | 
            +
                      # If username or password isn't provided, the user is asked on stdin
         | 
| 26 | 
            +
                      #{init} --auth basic --user user
         | 
| 27 | 
            +
                      Password: secret
         | 
| 28 | 
            +
                    END
         | 
| 29 29 |  | 
| 30 30 | 
             
                  when :token
         | 
| 31 | 
            -
                     | 
| 32 | 
            -
            # Get token using username and password and save it to disk
         | 
| 33 | 
            -
            # Note that the client always has to call some action. APIs should provide
         | 
| 34 | 
            -
            # an action to get information about the current user, so that's what we're
         | 
| 35 | 
            -
            # calling now.
         | 
| 36 | 
            -
            #{init} --auth token #{auth_token_credentials(desc, password: false).map { |k, v| "--#{k} #{v}" }.join(' ')} --save user current
         | 
| 37 | 
            -
            Password: secret
         | 
| 38 | 
            -
             | 
| 39 | 
            -
            # Now the token is read from disk and the user does not have to provide username
         | 
| 40 | 
            -
            # nor password and be authenticated
         | 
| 41 | 
            -
            #{init} user current
         | 
| 42 | 
            -
            END
         | 
| 31 | 
            +
                    <<~END
         | 
| 32 | 
            +
                      # Get token using username and password and save it to disk
         | 
| 33 | 
            +
                      # Note that the client always has to call some action. APIs should provide
         | 
| 34 | 
            +
                      # an action to get information about the current user, so that's what we're
         | 
| 35 | 
            +
                      # calling now.
         | 
| 36 | 
            +
                      #{init} --auth token #{auth_token_credentials(desc, password: false).map { |k, v| "--#{k} #{v}" }.join(' ')} --save user current
         | 
| 37 | 
            +
                      Password: secret
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                      # Now the token is read from disk and the user does not have to provide username
         | 
| 40 | 
            +
                      # nor password and be authenticated
         | 
| 41 | 
            +
                      #{init} user current
         | 
| 42 | 
            +
                    END
         | 
| 43 43 |  | 
| 44 44 | 
             
                  when :oauth2
         | 
| 45 45 | 
             
                    '# OAuth2 is not supported by HaveAPI Ruby CLI.'
         | 
| @@ -56,7 +56,7 @@ END | |
| 56 56 | 
             
                    cmd << "-- \\\n"
         | 
| 57 57 |  | 
| 58 58 | 
             
                    res = cmd.join(' ') + sample[:request].map do |k, v|
         | 
| 59 | 
            -
                      ' '*14 + input_param(k, v)
         | 
| 59 | 
            +
                      (' ' * 14) + input_param(k, v)
         | 
| 60 60 | 
             
                    end.join(" \\\n")
         | 
| 61 61 |  | 
| 62 62 | 
             
                  else
         | 
| @@ -84,32 +84,32 @@ END | |
| 84 84 |  | 
| 85 85 | 
             
                  action[:output][:parameters].each do |name, param|
         | 
| 86 86 | 
             
                    col = {
         | 
| 87 | 
            -
                        name | 
| 88 | 
            -
                        align: %w | 
| 89 | 
            -
                        label: param[:label] && !param[:label].empty? ? param[:label] : name.upcase | 
| 87 | 
            +
                        name:,
         | 
| 88 | 
            +
                        align: %w[Integer Float].include?(param[:type]) ? 'right' : 'left',
         | 
| 89 | 
            +
                        label: param[:label] && !param[:label].empty? ? param[:label] : name.upcase
         | 
| 90 90 | 
             
                    }
         | 
| 91 91 |  | 
| 92 92 | 
             
                    if param[:type] == 'Resource'
         | 
| 93 | 
            -
                      col[:display] =  | 
| 93 | 
            +
                      col[:display] = proc do |r|
         | 
| 94 94 | 
             
                        next '' unless r
         | 
| 95 95 | 
             
                        next r unless r.is_a?(::Hash)
         | 
| 96 96 |  | 
| 97 | 
            -
                        "#{r[ | 
| 97 | 
            +
                        "#{r[param[:value_label].to_sym]} (##{r[param[:value_id].to_sym]})"
         | 
| 98 98 | 
             
                      end
         | 
| 99 99 | 
             
                    end
         | 
| 100 100 |  | 
| 101 101 | 
             
                    cols << col
         | 
| 102 102 | 
             
                  end
         | 
| 103 103 |  | 
| 104 | 
            -
                  res << "\n" << HaveAPI::CLI::OutputFormatter. | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 104 | 
            +
                  res << "\n" << HaveAPI::CLI::OutputFormatter.to_s(
         | 
| 105 | 
            +
                    sample[:response],
         | 
| 106 | 
            +
                    cols
         | 
| 107 107 | 
             
                  )
         | 
| 108 108 | 
             
                  res
         | 
| 109 109 | 
             
                end
         | 
| 110 110 |  | 
| 111 111 | 
             
                def input_param(name, value)
         | 
| 112 | 
            -
                  option = name.to_s.gsub( | 
| 112 | 
            +
                  option = name.to_s.gsub('_', '-')
         | 
| 113 113 |  | 
| 114 114 | 
             
                  if action[:input][:parameters][name][:type] == 'Boolean'
         | 
| 115 115 | 
             
                    return value ? "--#{option}" : "--no-#{name}"
         | 
| @@ -8,34 +8,34 @@ module HaveAPI::ClientExamples | |
| 8 8 | 
             
                order 0
         | 
| 9 9 |  | 
| 10 10 | 
             
                def init
         | 
| 11 | 
            -
                   | 
| 12 | 
            -
            require 'haveapi-client'
         | 
| 11 | 
            +
                  <<~END
         | 
| 12 | 
            +
                    require 'haveapi-client'
         | 
| 13 13 |  | 
| 14 | 
            -
            client = HaveAPI::Client.new("#{base_url}", version: "#{version}")
         | 
| 15 | 
            -
            END
         | 
| 14 | 
            +
                    client = HaveAPI::Client.new("#{base_url}", version: "#{version}")
         | 
| 15 | 
            +
                  END
         | 
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 18 | 
             
                def auth(method, desc)
         | 
| 19 19 | 
             
                  case method
         | 
| 20 20 | 
             
                  when :basic
         | 
| 21 | 
            -
                     | 
| 22 | 
            -
            #{init}
         | 
| 21 | 
            +
                    <<~END
         | 
| 22 | 
            +
                      #{init}
         | 
| 23 23 |  | 
| 24 | 
            -
            client.authenticate(:basic, user: "user", password: "secret")
         | 
| 25 | 
            -
            END
         | 
| 24 | 
            +
                      client.authenticate(:basic, user: "user", password: "secret")
         | 
| 25 | 
            +
                    END
         | 
| 26 26 |  | 
| 27 27 | 
             
                  when :token
         | 
| 28 | 
            -
                     | 
| 29 | 
            -
            #{init}
         | 
| 28 | 
            +
                    <<~END
         | 
| 29 | 
            +
                      #{init}
         | 
| 30 30 |  | 
| 31 | 
            -
            # Get token using username and password
         | 
| 32 | 
            -
            client.authenticate(:token, #{auth_token_credentials(desc).map { |k, v| "#{k}: \"#{v}\"" }.join(', ')})
         | 
| 31 | 
            +
                      # Get token using username and password
         | 
| 32 | 
            +
                      client.authenticate(:token, #{auth_token_credentials(desc).map { |k, v| "#{k}: \"#{v}\"" }.join(', ')})
         | 
| 33 33 |  | 
| 34 | 
            -
            puts "Token = \#{client.auth.token}"
         | 
| 34 | 
            +
                      puts "Token = \#{client.auth.token}"
         | 
| 35 35 |  | 
| 36 | 
            -
            # Next time, the client can authenticate using the token directly
         | 
| 37 | 
            -
            client.authenticate(:token, token: saved_token)
         | 
| 38 | 
            -
            END
         | 
| 36 | 
            +
                      # Next time, the client can authenticate using the token directly
         | 
| 37 | 
            +
                      client.authenticate(:token, token: saved_token)
         | 
| 38 | 
            +
                    END
         | 
| 39 39 |  | 
| 40 40 | 
             
                  when :oauth2
         | 
| 41 41 | 
             
                    '# OAuth2 is not supported by HaveAPI Ruby client.'
         | 
| @@ -58,7 +58,7 @@ END | |
| 58 58 | 
             
                  return (out << response(sample)) if sample[:status]
         | 
| 59 59 |  | 
| 60 60 | 
             
                  out << "\n"
         | 
| 61 | 
            -
                  out <<  | 
| 61 | 
            +
                  out << '# Raises exception HaveAPI::Client::ActionFailed'
         | 
| 62 62 | 
             
                  out
         | 
| 63 63 | 
             
                end
         | 
| 64 64 |  | 
| @@ -79,29 +79,29 @@ END | |
| 79 79 | 
             
                  when :object
         | 
| 80 80 | 
             
                    out << "# reply is an instance of HaveAPI::Client::ResourceInstance\n"
         | 
| 81 81 |  | 
| 82 | 
            -
                    (sample[:response] || {}).each do | | 
| 82 | 
            +
                    (sample[:response] || {}).each do |pn, pv|
         | 
| 83 83 | 
             
                      param = action[:output][:parameters][k]
         | 
| 84 84 |  | 
| 85 85 | 
             
                      if param[:type] == 'Resource'
         | 
| 86 | 
            -
                        out << "# reply.#{ | 
| 86 | 
            +
                        out << "# reply.#{pn} = HaveAPI::Client::ResourceInstance("
         | 
| 87 87 | 
             
                        out << "resource: #{param[:resource].join('.')}, "
         | 
| 88 88 |  | 
| 89 | 
            -
                        if  | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 89 | 
            +
                        out << if pv.is_a?(::Hash)
         | 
| 90 | 
            +
                                 pv.map { |k, v| "#{k}: #{PP.pp(v, '').strip}" }.join(', ')
         | 
| 91 | 
            +
                               else
         | 
| 92 | 
            +
                                 "id: #{pv}"
         | 
| 93 | 
            +
                               end
         | 
| 94 94 |  | 
| 95 95 | 
             
                        out << ")\n"
         | 
| 96 96 |  | 
| 97 97 | 
             
                      else
         | 
| 98 | 
            -
                        out << "# reply.#{ | 
| 98 | 
            +
                        out << "# reply.#{pn} = #{PP.pp(pv, '')}"
         | 
| 99 99 | 
             
                      end
         | 
| 100 100 | 
             
                    end
         | 
| 101 101 |  | 
| 102 102 | 
             
                  when :object_list
         | 
| 103 103 | 
             
                    out << "# reply is an instance of HaveAPI::Client::ResourceInstanceList,\n"
         | 
| 104 | 
            -
                    out <<  | 
| 104 | 
            +
                    out << '# which is a subclass of Array'
         | 
| 105 105 | 
             
                  end
         | 
| 106 106 |  | 
| 107 107 | 
             
                  out
         | 
    
        data/lib/haveapi/common.rb
    CHANGED
    
    | @@ -3,13 +3,13 @@ module HaveAPI | |
| 3 3 | 
             
                class << self
         | 
| 4 4 | 
             
                  attr_accessor :custom_attrs
         | 
| 5 5 |  | 
| 6 | 
            -
                  def has_attr(name, default=nil)
         | 
| 6 | 
            +
                  def has_attr(name, default = nil)
         | 
| 7 7 | 
             
                    @custom_attrs ||= []
         | 
| 8 8 | 
             
                    @custom_attrs << name
         | 
| 9 9 |  | 
| 10 10 | 
             
                    instance_variable_set("@#{name}", default)
         | 
| 11 11 |  | 
| 12 | 
            -
                    self.class.send(:define_method, name) do |value=nil|
         | 
| 12 | 
            +
                    self.class.send(:define_method, name) do |value = nil|
         | 
| 13 13 | 
             
                      if value.nil?
         | 
| 14 14 | 
             
                        instance_variable_get("@#{name}")
         | 
| 15 15 | 
             
                      else
         | 
| @@ -34,8 +34,7 @@ module HaveAPI | |
| 34 34 |  | 
| 35 35 | 
             
                  def check_build(msg)
         | 
| 36 36 | 
             
                    yield
         | 
| 37 | 
            -
                  
         | 
| 38 | 
            -
                  rescue => e
         | 
| 37 | 
            +
                  rescue StandardError => e
         | 
| 39 38 | 
             
                    raise BuildError.new(msg, e)
         | 
| 40 39 | 
             
                  end
         | 
| 41 40 | 
             
                end
         | 
    
        data/lib/haveapi/context.rb
    CHANGED
    
    | @@ -5,8 +5,8 @@ module HaveAPI | |
| 5 5 | 
             
                              :action_instance, :action_prepare, :layout
         | 
| 6 6 |  | 
| 7 7 | 
             
                def initialize(server, version: nil, request: nil, resource: [], action: nil,
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 8 | 
            +
                               path: nil, args: nil, params: nil, user: nil,
         | 
| 9 | 
            +
                               authorization: nil, endpoint: nil, resource_path: [])
         | 
| 10 10 | 
             
                  @server = server
         | 
| 11 11 | 
             
                  @version = version
         | 
| 12 12 | 
             
                  @request = request
         | 
| @@ -33,7 +33,7 @@ module HaveAPI | |
| 33 33 | 
             
                  ret
         | 
| 34 34 | 
             
                end
         | 
| 35 35 |  | 
| 36 | 
            -
                def path_for(action, args=nil)
         | 
| 36 | 
            +
                def path_for(action, args = nil)
         | 
| 37 37 | 
             
                  top_module = Kernel
         | 
| 38 38 | 
             
                  top_route = @server.routes[@version]
         | 
| 39 39 |  | 
| @@ -42,16 +42,15 @@ module HaveAPI | |
| 42 42 |  | 
| 43 43 | 
             
                    begin
         | 
| 44 44 | 
             
                      top_module.obj_type
         | 
| 45 | 
            -
             | 
| 46 45 | 
             
                    rescue NoMethodError
         | 
| 47 46 | 
             
                      next
         | 
| 48 47 | 
             
                    end
         | 
| 49 48 |  | 
| 50 | 
            -
                    if top_module.obj_type == :resource
         | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 49 | 
            +
                    top_route = if top_module.obj_type == :resource
         | 
| 50 | 
            +
                                  top_route[:resources][top_module]
         | 
| 51 | 
            +
                                else
         | 
| 52 | 
            +
                                  top_route[:actions][top_module]
         | 
| 53 | 
            +
                                end
         | 
| 55 54 | 
             
                  end
         | 
| 56 55 |  | 
| 57 56 | 
             
                  ret = top_route.dup
         | 
| @@ -65,6 +64,7 @@ module HaveAPI | |
| 65 64 | 
             
                  ret = params && action.resolve_path_params(obj)
         | 
| 66 65 |  | 
| 67 66 | 
             
                  return [ret] if ret && !ret.is_a?(Array)
         | 
| 67 | 
            +
             | 
| 68 68 | 
             
                  ret
         | 
| 69 69 | 
             
                end
         | 
| 70 70 |  | 
| @@ -87,10 +87,11 @@ module HaveAPI | |
| 87 87 | 
             
                end
         | 
| 88 88 |  | 
| 89 89 | 
             
                def action_scope
         | 
| 90 | 
            -
                  resource_path.map(&:downcase).join('.') | 
| 90 | 
            +
                  "#{resource_path.map(&:downcase).join('.')}##{action.action_name.underscore}"
         | 
| 91 91 | 
             
                end
         | 
| 92 92 |  | 
| 93 93 | 
             
                private
         | 
| 94 | 
            +
             | 
| 94 95 | 
             
                def resolve_arg!(path, arg)
         | 
| 95 96 | 
             
                  path.sub!(/\{[a-zA-Z\-_]+\}/, arg.to_s)
         | 
| 96 97 | 
             
                end
         | 
    
        data/lib/haveapi/example.rb
    CHANGED
    
    | @@ -50,9 +50,13 @@ module HaveAPI | |
| 50 50 | 
             
                end
         | 
| 51 51 |  | 
| 52 52 | 
             
                def provided?
         | 
| 53 | 
            -
                  instance_variables.detect do |v|
         | 
| 53 | 
            +
                  if instance_variables.detect do |v|
         | 
| 54 54 | 
             
                    instance_variable_get(v)
         | 
| 55 | 
            -
                  end | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                    true
         | 
| 57 | 
            +
                  else
         | 
| 58 | 
            +
                    false
         | 
| 59 | 
            +
                  end
         | 
| 56 60 | 
             
                end
         | 
| 57 61 |  | 
| 58 62 | 
             
                def describe(context)
         | 
| @@ -66,7 +70,7 @@ module HaveAPI | |
| 66 70 | 
             
                      status: @status.nil? ? true : @status,
         | 
| 67 71 | 
             
                      message: @message,
         | 
| 68 72 | 
             
                      errors: @errors,
         | 
| 69 | 
            -
                      http_status: @http_status || 200 | 
| 73 | 
            +
                      http_status: @http_status || 200
         | 
| 70 74 | 
             
                    }
         | 
| 71 75 | 
             
                  else
         | 
| 72 76 | 
             
                    {}
         | 
| @@ -74,12 +78,13 @@ module HaveAPI | |
| 74 78 | 
             
                end
         | 
| 75 79 |  | 
| 76 80 | 
             
                protected
         | 
| 81 | 
            +
             | 
| 77 82 | 
             
                def filter_input_params(context, input)
         | 
| 78 83 | 
             
                  case context.action.input.layout
         | 
| 79 84 | 
             
                  when :object, :hash
         | 
| 80 85 | 
             
                    context.authorization.filter_input(
         | 
| 81 86 | 
             
                      context.action.input.params,
         | 
| 82 | 
            -
                      ModelAdapters::Hash.output(context, input) | 
| 87 | 
            +
                      ModelAdapters::Hash.output(context, input)
         | 
| 83 88 | 
             
                    )
         | 
| 84 89 |  | 
| 85 90 | 
             
                  when :object_list, :hash_list
         | 
    
        data/lib/haveapi/example_list.rb
    CHANGED
    
    
    
        data/lib/haveapi/exceptions.rb
    CHANGED
    
    
| @@ -4,7 +4,7 @@ module HaveAPI::Extensions | |
| 4 4 | 
             
              class ActionExceptions < Base
         | 
| 5 5 | 
             
                class << self
         | 
| 6 6 | 
             
                  def enabled(server)
         | 
| 7 | 
            -
                    HaveAPI::Action.connect_hook(:exec_exception) do |ret,  | 
| 7 | 
            +
                    HaveAPI::Action.connect_hook(:exec_exception) do |ret, _context, e|
         | 
| 8 8 | 
             
                      break(ret) unless @exceptions
         | 
| 9 9 |  | 
| 10 10 | 
             
                      @exceptions.each do |handler|
         | 
| @@ -20,7 +20,7 @@ module HaveAPI::Extensions | |
| 20 20 |  | 
| 21 21 | 
             
                  def rescue(klass, &block)
         | 
| 22 22 | 
             
                    @exceptions ||= []
         | 
| 23 | 
            -
                    @exceptions << { | 
| 23 | 
            +
                    @exceptions << { klass:, block: }
         | 
| 24 24 | 
             
                  end
         | 
| 25 25 | 
             
                end
         | 
| 26 26 | 
             
              end
         |