assently 1.0.0.beta1

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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +15 -0
  6. data/Gemfile +10 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +124 -0
  9. data/Rakefile +1 -0
  10. data/assently.gemspec +31 -0
  11. data/lib/assently/api_mappers/case_event_subscription_mapper.rb +12 -0
  12. data/lib/assently/api_mappers/case_mapper.rb +23 -0
  13. data/lib/assently/api_mappers/case_options_mapper.rb +74 -0
  14. data/lib/assently/api_mappers/document_mapper.rb +19 -0
  15. data/lib/assently/api_mappers/form_field_mapper.rb +12 -0
  16. data/lib/assently/api_mappers/party_mapper.rb +13 -0
  17. data/lib/assently/case.rb +50 -0
  18. data/lib/assently/case_event_subscription.rb +29 -0
  19. data/lib/assently/client.rb +129 -0
  20. data/lib/assently/document.rb +64 -0
  21. data/lib/assently/form_field.rb +3 -0
  22. data/lib/assently/id_generator.rb +10 -0
  23. data/lib/assently/party.rb +21 -0
  24. data/lib/assently/serializers/case_serializer.rb +15 -0
  25. data/lib/assently/version.rb +3 -0
  26. data/lib/assently.rb +14 -0
  27. data/spec/assently/api_mappers/case_event_subscription_mapper_spec.rb +23 -0
  28. data/spec/assently/api_mappers/case_mapper_spec.rb +34 -0
  29. data/spec/assently/api_mappers/case_options_mapper_spec.rb +92 -0
  30. data/spec/assently/api_mappers/document_mapper_spec.rb +35 -0
  31. data/spec/assently/api_mappers/form_field_mapper_spec.rb +19 -0
  32. data/spec/assently/api_mappers/party_mapper_spec.rb +24 -0
  33. data/spec/assently/case_event_subscription_spec.rb +18 -0
  34. data/spec/assently/case_spec.rb +68 -0
  35. data/spec/assently/client/create_case_spec.rb +55 -0
  36. data/spec/assently/client/get_case_spec.rb +84 -0
  37. data/spec/assently/client_spec.rb +207 -0
  38. data/spec/assently/document_spec.rb +126 -0
  39. data/spec/assently/form_field_spec.rb +18 -0
  40. data/spec/assently/id_generator_spec.rb +13 -0
  41. data/spec/assently/party_spec.rb +35 -0
  42. data/spec/assently/serializers/case_serializer_spec.rb +39 -0
  43. data/spec/assently_spec.rb +17 -0
  44. data/spec/fixtures/agreement.pdf +0 -0
  45. data/spec/fixtures/cassettes/Assently_Client/_create_case/valid_case.yml +75 -0
  46. data/spec/fixtures/cassettes/Assently_Client/_get_case/case_exists.yml +107 -0
  47. data/spec/fixtures/cassettes/Assently_Client/_get_case/case_missing.yml +43 -0
  48. data/spec/spec_helper.rb +38 -0
  49. metadata +225 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 933080f44f336e051125aa02137fbb9ce032f19b
4
+ data.tar.gz: 4ba7f86ccd3e8466e4926c10fa394f078f9cce25
5
+ SHA512:
6
+ metadata.gz: 3862f68bb0b1756e8bfc6934dc0d8a7e07d4a7593dbd1551a42899489b80a444e644bc811d35080fe13613e62585276ba4c1b07b0763a6e9106b294f66ddf0aa
7
+ data.tar.gz: f8e1f8e5d1ef32f5bf33c8ab6852f2131bfcecbfadf445f319e8140db471f9ef3e28f1ff3906cd5a0bd57f9826580b1e683838aed1e199a1340a74abd9312a80
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .env
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ bin/
20
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.4.0
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.4.0
4
+ - 2.3.3
5
+ script: rspec spec
6
+ addons:
7
+ code_climate:
8
+ repo_token:
9
+ secure: MYIsQJ3/wQ6xBYaWCwgG1HRyrH7MH4vME+ACEbM9poMun6jgvFu7Unc0eGpjMxzytophN5o7j0LTc6xxNCMCz6UGFK8Y7RP9/fii6bLFdqROS7jrxYf6tFwKXO4bAhhOZdZjyuYEFiRxImNHPXka+ap4vOnP/QW3D8l94lrAyoM=
10
+ after_success:
11
+ - bundle exec codeclimate-test-reporter
12
+ env:
13
+ global:
14
+ - secure: NOH9DBJdldYSVadf2zAYPtP7Nke3k4rdrsXv2uBLelHwuZhmrRRprdgM2h3igheiq2j/OcbZSZeNgLMWY06A+RhxQzUOKUDBFcUs9QL23xgKFZcRi3YNqhhLC/LRXo4gmpL4J7OFJqMySTlaIWHRFqLJoFdoHTut3YKAChea4xE=
15
+ - secure: KQ/hQWZ1UTkbrfBUqy5qU/tw1YVpPSNtMnsNuammiBq9xJL2hkwIBiOwKmnC6rb48KhkCGCSmKU1CLvsqmAEncwF8vBXzrFPgQdg7JQN9Wn0gb2ESCnhfIP0rFfoKLZI9YVP3SB8YsfODlfNJwjKhAqsI6mCoQ/jN7yX8bvfnlM=
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "simplecov"
7
+ gem "codeclimate-test-reporter", "~> 1.0.0"
8
+ gem "pry"
9
+ end
10
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Joel Junström
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ [![Build Status](https://travis-ci.org/Oktavilla/egree-ruby.svg?branch=master)](https://travis-ci.org/Oktavilla/egree-ruby)
2
+ [![Code Climate](https://codeclimate.com/github/Oktavilla/egree-ruby/badges/gpa.svg)](https://codeclimate.com/github/Oktavilla/egree-ruby)
3
+ [![Test Coverage](https://codeclimate.com/github/Oktavilla/egree-ruby/badges/coverage.svg)](https://codeclimate.com/github/Oktavilla/egree-ruby)
4
+ [![Gem Version](https://badge.fury.io/rb/egree.svg)](http://badge.fury.io/rb/egree)
5
+
6
+ # Assently API Client
7
+
8
+ Ruby client for the [Assently API v2](https://assently.com/). Check out [the official API documentation here](https://app.assently.com/api/).
9
+
10
+ ### Supported API calls
11
+
12
+ | API call | Supported |
13
+ |----------|:-------------:|
14
+ | `createcase` | ✔️ |
15
+ | `sendcase` | ✔️|
16
+ | `getcase` | ✔️|
17
+ | `createcasefromtemplate ` | |
18
+ | `updatecase ` | |
19
+ | `remindcase ` | |
20
+ | `deletecase ` | |
21
+ | `recallcase ` | |
22
+ | `findcases ` | |
23
+ | `findtemplates ` | |
24
+ | `getdocumentdata ` | |
25
+ | `createagent ` | |
26
+ | `createssoticket ` | |
27
+
28
+ Missing something? Contributions are very welcome! 😘
29
+
30
+ ## Installation
31
+
32
+ Include the gem in your `Gemfile`:
33
+
34
+ ```ruby
35
+ gem "assently"
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ ### Environment
41
+
42
+ When creating a client instance you can choose to use either Assently's `production` (default when not specified) or `test` environment. The host `app.assently.com` is used for production and `test.assently.com` is used for test when constructing the API commands. Test environment is specified like this:
43
+
44
+ ```ruby
45
+ Assently.client ENV["ASSENTLY_API_KEY"], ENV["ASSENTLY_API_SECRET"], :test
46
+ ```
47
+
48
+ ### Creating a case
49
+
50
+ ```ruby
51
+ assently = Assently.client assently_api_key, assently_api_secret
52
+
53
+ case_id = SecureRandom.uuid
54
+
55
+ signature_case = Assently::Case.new "Agreement", ["electronicid"], id: case_id
56
+ signature_case.add_party Assently::Party.new_with_attributes({
57
+ name: "First Last",
58
+ email: "name@example.com",
59
+ social_security_number: "1234567890"
60
+ })
61
+ signature_case.add_document Assently::Document.new "/some/path/file.pdf"
62
+
63
+ event_subscription = Assently::CaseEventSubscription.new ["finished", "expired"], "https://example.com/my-endpoint"
64
+
65
+ result = assently.create_case(signature_case, {
66
+ # Callback for document events
67
+ event_callback: event_subscription,
68
+ # User ends up here after finishing the signing process
69
+ continue: {
70
+ url: "http://example.com/user-endpoint",
71
+ auto: true
72
+ },
73
+ # User ends up here when cancelling, at the moment there is no cancel callback
74
+ cancel_url: "http://example.com/user-canceled"
75
+ })
76
+
77
+ if result.success?
78
+ puts "#{signature_case.id} was created."
79
+ else
80
+ puts "There was some issues with the case"
81
+ result.errors.each do |error|
82
+ puts error
83
+ end
84
+ end
85
+ ```
86
+
87
+ ### Making a case available for signing
88
+
89
+ ```ruby
90
+ assently = Assently.client API_KEY, API_SECRET
91
+ result = assently.get_case case_id
92
+
93
+ if result.success?
94
+ assently.send_case case_id
95
+
96
+ signing_case = assently.get_case case_id
97
+
98
+ puts "Sign it here: #{signing_case.response["Parties"].first["PartyUrl"]}"
99
+ else
100
+ puts "Could not get signature url"
101
+ result.errors.each do |error|
102
+ puts error
103
+ end
104
+ end
105
+ ```
106
+
107
+ ### Local development
108
+
109
+ Create a `.env` file in the root directory to run the integration tests against your Assently test environment.
110
+
111
+ ```sh
112
+ ASSENTLY_API_KEY=your-api-key
113
+ ASSENTLY_API_KEY=your-api-secret
114
+ ```
115
+
116
+
117
+ ## Contributing
118
+
119
+ Contributions is more than welcome!
120
+
121
+ Just create a fork and submit a pull request.
122
+
123
+ Please adhere to the coding standards used in the project and add tests.
124
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/assently.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'assently/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "assently"
8
+ spec.version = Assently::VERSION
9
+ spec.authors = ["Joel Junström"]
10
+ spec.email = ["joel.junstrom@oktavilla.se"]
11
+ spec.summary = %q{Client for the Assently APIv2}
12
+ spec.homepage = "https://github.com/Oktavilla/egree-ruby"
13
+ spec.license = "MIT"
14
+
15
+ spec.required_ruby_version = "~> 2.0"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "http", "~> 2.2"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.14"
25
+ spec.add_development_dependency "dotenv", "~> 2.1"
26
+ spec.add_development_dependency "rake"
27
+ spec.add_development_dependency "rspec"
28
+ spec.add_development_dependency "webmock", "~> 2.3"
29
+ spec.add_development_dependency "vcr", "~> 3.0"
30
+ spec.add_development_dependency "luhn", "~> 1.0"
31
+ end
@@ -0,0 +1,12 @@
1
+ module Assently
2
+ module ApiMappers
3
+ module CaseEventSubscriptionMapper
4
+ def self.to_api case_event_subscription
5
+ {
6
+ "Events" => case_event_subscription.events,
7
+ "Url" => case_event_subscription.url
8
+ }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ require "json"
2
+ require "assently/api_mappers/party_mapper"
3
+ require "assently/api_mappers/document_mapper"
4
+
5
+ module Assently
6
+ module ApiMappers
7
+ module CaseMapper
8
+ def self.to_api signature_case
9
+ {
10
+ "Id" => signature_case.id,
11
+ "Name" => signature_case.name,
12
+ "Documents" => signature_case.documents.map { |document|
13
+ Assently::ApiMappers::DocumentMapper.to_api(document)
14
+ },
15
+ "Parties" => signature_case.parties.map { |party|
16
+ Assently::ApiMappers::PartyMapper.to_api(party)
17
+ },
18
+ "AllowedSignatureTypes" => signature_case.signature_types
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,74 @@
1
+ require "assently/api_mappers/case_event_subscription_mapper"
2
+
3
+ module Assently
4
+ class InvalidCaseOptionError < ArgumentError; end
5
+
6
+ module ApiMappers
7
+ module CaseOptionsMapper
8
+ def self.to_api options = {}, mappers = self.mappers
9
+ options.reduce({}) do |api_hash, (client_key, value)|
10
+ if mappers.key?(client_key)
11
+ api_hash.merge(self.map(client_key, value, mappers))
12
+ else
13
+ api_hash
14
+ end
15
+ end || {}
16
+ end
17
+
18
+ private
19
+
20
+ LOCALES = ->(locale) {
21
+ {
22
+ "sv" => "sv-SE",
23
+ "fi" => "fi-FI",
24
+ "en" => "en-US"
25
+ }.fetch(locale) { raise Assently::InvalidCaseOptionError.new("Unknown locale: #{locale}") }
26
+ }
27
+
28
+ def self.map client_key, value, mappers = self.mappers
29
+ mapper = mappers[client_key]
30
+
31
+ if mapper.respond_to?(:call)
32
+ mapper.call value
33
+ else
34
+ { mapper => value }
35
+ end
36
+ end
37
+
38
+ def self.mappers
39
+ {
40
+ name_alias: "NameAlias",
41
+ agent_username: "AgentUsername",
42
+ visibility: "Visibility",
43
+ description: "Description",
44
+ send_sign_request_email_to_parties: "SendSignRequestEmailToParties",
45
+ send_finish_email_to_creator: "SendFinishEmailToCreator",
46
+ send_finish_email_to_parties: "SendFinishEmailToParties",
47
+ send_recall_email_to_parties: "SendRecallEmailToParties",
48
+ cancel_url: "CancelUrl",
49
+ procedure: "Procedure",
50
+ locale: ->(value) {
51
+ { "Culture" => LOCALES.call(value) }
52
+ },
53
+ continue: ->(options) {
54
+ CaseOptionsMapper.to_api options, name: "ContinueName", url: "ContinueUrl", auto: "ContinueAuto"
55
+ },
56
+ sign_in_sequence: "SignInSequence",
57
+ identity_check: "IdentityCheck",
58
+ merge_on_send: "MergeOnSend",
59
+ expire_after_days: "ExpireAfterDays",
60
+ expire_on: ->(value) {
61
+ { "ExpireOn" => value.iso8601 }
62
+ },
63
+ remind_ander_days: "RemindAfterDays",
64
+ template_id: "TemplateId",
65
+ is_editable: "IsEditable",
66
+ event_callback: ->(value) {
67
+ { "EventCallback" => CaseEventSubscriptionMapper.to_api(value) }
68
+ },
69
+ meta_data: "MetaData"
70
+ }
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,19 @@
1
+ require "assently/api_mappers/form_field_mapper"
2
+
3
+ module Assently
4
+ module ApiMappers
5
+ module DocumentMapper
6
+ def self.to_api document
7
+ {
8
+ "Filename" => document.filename,
9
+ "Data" => document.data,
10
+ "ContentType" => document.content_type,
11
+ "Size" => document.size,
12
+ "FormFields" => document.form_fields.map { |form_field|
13
+ Assently::ApiMappers::FormFieldMapper.to_api(form_field)
14
+ }
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ module Assently
2
+ module ApiMappers
3
+ module FormFieldMapper
4
+ def self.to_api form_field
5
+ {
6
+ "Name" => form_field.name,
7
+ "Value" => form_field.value
8
+ }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Assently
2
+ module ApiMappers
3
+ module PartyMapper
4
+ def self.to_api party
5
+ {
6
+ "Name" => party.name,
7
+ "EmailAddress" => party.email,
8
+ "SocialSecurityNumber" => party.social_security_number
9
+ }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,50 @@
1
+ require "assently/id_generator"
2
+
3
+ module Assently
4
+ class Case
5
+ def self.signature_types
6
+ [ "sms", "electronicid", "touch", "quickintent", "signbyhand" ]
7
+ end
8
+
9
+ attr_reader :name, :signature_types, :id
10
+
11
+ def initialize name, signature_types, id: nil
12
+ @name = name
13
+ @id = id || IdGenerator.generate
14
+ self.signature_types = signature_types
15
+ end
16
+
17
+ def signature_types= signature_types
18
+ types = Array(signature_types)
19
+
20
+ unknown_types = types - Case.signature_types
21
+ if unknown_types.any?
22
+ raise unknown_signature_type_error(unknown_types)
23
+ end
24
+
25
+ @signature_types = types
26
+ end
27
+
28
+ def add_party party
29
+ self.parties << party
30
+ end
31
+
32
+ def parties
33
+ @parties ||= []
34
+ end
35
+
36
+ def add_document document
37
+ self.documents << document
38
+ end
39
+
40
+ def documents
41
+ @documents ||= []
42
+ end
43
+
44
+ private
45
+
46
+ def unknown_signature_type_error types
47
+ ArgumentError.new("Unknown signature types: #{types.join(", ")}. Valid types are: #{Case.signature_types.join(", ")}")
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,29 @@
1
+ module Assently
2
+ class CaseEventSubscription
3
+ attr_reader :events, :url
4
+
5
+ def self.events
6
+ [ "created", "sent", "recalled", "finished", "rejected", "expired", "deleted", "signatureadded", "approvalrequested", "reminded" ]
7
+ end
8
+
9
+ def initialize(events, url)
10
+ self.events = events
11
+ @url = url
12
+ end
13
+
14
+ def events= events
15
+ unknown_events = events - CaseEventSubscription.events
16
+ if unknown_events.any?
17
+ raise unknown_event_error(unknown_events)
18
+ end
19
+
20
+ @events = events
21
+ end
22
+
23
+ private
24
+
25
+ def unknown_event_error events
26
+ ArgumentError.new("Unknown events: #{events.join(", ")}. Valid events are: #{CaseEventSubscription.events.join(", ")}")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,129 @@
1
+ require "json"
2
+ require "http"
3
+
4
+ require "assently/serializers/case_serializer"
5
+
6
+ module Assently
7
+ class Client
8
+ attr_reader :api_key, :api_secret
9
+
10
+ attr_accessor :environment
11
+
12
+ def initialize api_key, api_secret, environment = :production
13
+ @api_key = api_key
14
+ @api_secret = api_secret
15
+ self.environment = environment
16
+ end
17
+
18
+ def create_case signature_case, options = {}
19
+ signature_case_json = Assently::Serializers::CaseSerializer.serialize signature_case, options
20
+
21
+ post "/api/v2/createcase", signature_case_json
22
+ end
23
+
24
+ def send_case id
25
+ post "/api/v2/sendcase", JSON.pretty_generate({ id: id })
26
+ end
27
+
28
+ def get_case id
29
+ get "/api/v2/getcase", { id: id }
30
+ end
31
+
32
+ def post api_command, body = nil
33
+ make_response make_post(api_command, body)
34
+ end
35
+
36
+ def get api_command, parameters = {}
37
+ make_response make_get(api_command, parameters)
38
+ end
39
+
40
+ def host
41
+ hosts.fetch(self.environment, hosts[:production])
42
+ end
43
+
44
+ def connection
45
+ HTTP.
46
+ headers(accept: "application/json").
47
+ basic_auth(user: api_key, pass: api_secret)
48
+ end
49
+
50
+ def headers
51
+ connection.headers
52
+ end
53
+
54
+ private
55
+
56
+ def api_base_url
57
+ "https://#{host}"
58
+ end
59
+
60
+ def api_url path
61
+ URI.join(api_base_url, path)
62
+ end
63
+
64
+ def make_response response
65
+ if response.status.success?
66
+ SuccessResult.new response.body.to_s
67
+ else
68
+ ErrorResult.new response.body.to_s
69
+ end
70
+ end
71
+
72
+ def make_post path, body
73
+ connection.
74
+ headers(content_type: "application/json; charset=utf-8").
75
+ post api_url(path), body: body
76
+ end
77
+
78
+ def make_get path, parameters
79
+ connection.get api_url(path), params: parameters
80
+ end
81
+
82
+ def hosts
83
+ {
84
+ production: "app.assently.com",
85
+ test: "test.assently.com"
86
+ }
87
+ end
88
+
89
+ class SuccessResult
90
+ attr_reader :raw
91
+
92
+ def initialize response
93
+ @raw = response
94
+ end
95
+
96
+ def response
97
+ begin
98
+ JSON.parse raw
99
+ rescue JSON::ParserError
100
+ raw
101
+ end
102
+ end
103
+
104
+ def success?
105
+ true
106
+ end
107
+ end
108
+
109
+ class ErrorResult
110
+ attr_reader :raw
111
+
112
+ def initialize response
113
+ @raw = response
114
+ end
115
+
116
+ def errors
117
+ begin
118
+ Array(JSON.parse(raw)["error"].values.join(" "))
119
+ rescue JSON::ParserError
120
+ raw
121
+ end
122
+ end
123
+
124
+ def success?
125
+ false
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,64 @@
1
+ require "open-uri"
2
+ require "base64"
3
+
4
+ module Assently
5
+ class CouldNotFetchDocumentError < StandardError
6
+ end
7
+
8
+ class Document
9
+ attr_reader :path, :username, :password
10
+
11
+ def initialize path, filename: nil, username: nil, password: nil
12
+ @path = path
13
+ @filename = filename
14
+ @username = username
15
+ @password = password
16
+ end
17
+
18
+ def filename
19
+ @filename || File.basename(path)
20
+ end
21
+
22
+ def size
23
+ file.size
24
+ end
25
+
26
+ def content_type
27
+ "application/pdf"
28
+ end
29
+
30
+ def data
31
+ Base64.encode64 file_contents
32
+ end
33
+
34
+ def add_form_field form_field
35
+ self.form_fields << form_field
36
+ end
37
+
38
+ def form_fields
39
+ @form_fields ||= []
40
+ end
41
+
42
+ private
43
+
44
+ def file_contents
45
+ file.read
46
+ end
47
+
48
+ def file
49
+ begin
50
+ open path, authentication_params
51
+ rescue OpenURI::HTTPError => error
52
+ raise Assently::CouldNotFetchDocumentError.new("Could not get url #{path} (#{error.message})")
53
+ end
54
+ end
55
+
56
+ def authentication_params
57
+ if username && password
58
+ { http_basic_authentication: [ username, password ] }
59
+ else
60
+ {}
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module Assently
2
+ FormField = Struct.new :name, :value
3
+ end