docusign_dtr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +33 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +73 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/certs/shanedavies.pem +25 -0
  14. data/docusign_dtr.gemspec +41 -0
  15. data/lib/docusign_dtr/activity.rb +17 -0
  16. data/lib/docusign_dtr/auth/base.rb +87 -0
  17. data/lib/docusign_dtr/auth/code.rb +43 -0
  18. data/lib/docusign_dtr/auth/jwt.rb +51 -0
  19. data/lib/docusign_dtr/client.rb +98 -0
  20. data/lib/docusign_dtr/document.rb +34 -0
  21. data/lib/docusign_dtr/exceptions.rb +6 -0
  22. data/lib/docusign_dtr/member.rb +30 -0
  23. data/lib/docusign_dtr/meta.rb +17 -0
  24. data/lib/docusign_dtr/meta_activity_type.rb +17 -0
  25. data/lib/docusign_dtr/meta_closing_status.rb +17 -0
  26. data/lib/docusign_dtr/meta_contact_side.rb +17 -0
  27. data/lib/docusign_dtr/meta_country.rb +17 -0
  28. data/lib/docusign_dtr/meta_currency.rb +17 -0
  29. data/lib/docusign_dtr/meta_financing_type.rb +17 -0
  30. data/lib/docusign_dtr/meta_origin_of_lead_type.rb +17 -0
  31. data/lib/docusign_dtr/meta_property_type.rb +17 -0
  32. data/lib/docusign_dtr/meta_role.rb +17 -0
  33. data/lib/docusign_dtr/meta_room_contact_type.rb +17 -0
  34. data/lib/docusign_dtr/meta_seller_decision_type.rb +17 -0
  35. data/lib/docusign_dtr/meta_special_circumstance_type.rb +17 -0
  36. data/lib/docusign_dtr/meta_state.rb +17 -0
  37. data/lib/docusign_dtr/meta_task_date_type.rb +17 -0
  38. data/lib/docusign_dtr/meta_timezone.rb +17 -0
  39. data/lib/docusign_dtr/meta_transaction_side.rb +17 -0
  40. data/lib/docusign_dtr/models/activity.rb +14 -0
  41. data/lib/docusign_dtr/models/address.rb +15 -0
  42. data/lib/docusign_dtr/models/auction_detail.rb +21 -0
  43. data/lib/docusign_dtr/models/auth_config.rb +15 -0
  44. data/lib/docusign_dtr/models/auth_token_response.rb +11 -0
  45. data/lib/docusign_dtr/models/contact.rb +28 -0
  46. data/lib/docusign_dtr/models/creation_detail.rb +11 -0
  47. data/lib/docusign_dtr/models/document.rb +50 -0
  48. data/lib/docusign_dtr/models/lone_wolf_commission.rb +11 -0
  49. data/lib/docusign_dtr/models/lone_wolf_detail.rb +14 -0
  50. data/lib/docusign_dtr/models/member.rb +20 -0
  51. data/lib/docusign_dtr/models/meta.rb +11 -0
  52. data/lib/docusign_dtr/models/meta_activity_type.rb +6 -0
  53. data/lib/docusign_dtr/models/meta_closing_status.rb +6 -0
  54. data/lib/docusign_dtr/models/meta_contact_side.rb +6 -0
  55. data/lib/docusign_dtr/models/meta_country.rb +6 -0
  56. data/lib/docusign_dtr/models/meta_currency.rb +6 -0
  57. data/lib/docusign_dtr/models/meta_financing_type.rb +6 -0
  58. data/lib/docusign_dtr/models/meta_origin_of_lead_type.rb +6 -0
  59. data/lib/docusign_dtr/models/meta_property_type.rb +6 -0
  60. data/lib/docusign_dtr/models/meta_role.rb +6 -0
  61. data/lib/docusign_dtr/models/meta_room_contact_type.rb +6 -0
  62. data/lib/docusign_dtr/models/meta_seller_decision_type.rb +6 -0
  63. data/lib/docusign_dtr/models/meta_special_circumstance_type.rb +6 -0
  64. data/lib/docusign_dtr/models/meta_state.rb +6 -0
  65. data/lib/docusign_dtr/models/meta_task_date_type.rb +6 -0
  66. data/lib/docusign_dtr/models/meta_timezone.rb +6 -0
  67. data/lib/docusign_dtr/models/meta_transaction_side.rb +6 -0
  68. data/lib/docusign_dtr/models/office.rb +15 -0
  69. data/lib/docusign_dtr/models/owner.rb +12 -0
  70. data/lib/docusign_dtr/models/profile.rb +28 -0
  71. data/lib/docusign_dtr/models/room.rb +45 -0
  72. data/lib/docusign_dtr/models/room_detail.rb +95 -0
  73. data/lib/docusign_dtr/models/task.rb +56 -0
  74. data/lib/docusign_dtr/models/task_list.rb +22 -0
  75. data/lib/docusign_dtr/models/title.rb +11 -0
  76. data/lib/docusign_dtr/models/user.rb +29 -0
  77. data/lib/docusign_dtr/office.rb +17 -0
  78. data/lib/docusign_dtr/profile.rb +16 -0
  79. data/lib/docusign_dtr/room.rb +30 -0
  80. data/lib/docusign_dtr/task_list.rb +24 -0
  81. data/lib/docusign_dtr/title.rb +17 -0
  82. data/lib/docusign_dtr/user.rb +31 -0
  83. data/lib/docusign_dtr/version.rb +3 -0
  84. data/lib/docusign_dtr.rb +92 -0
  85. data.tar.gz.sig +0 -0
  86. metadata +349 -0
  87. metadata.gz.sig +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1fc2fec821cff482ea06b2492c22a3ee5096724e645fbf80f4cf95bffabfb545
4
+ data.tar.gz: 1203596c16a182231f760ec48162a6341e97487b7a77d4001754ef266691dc3b
5
+ SHA512:
6
+ metadata.gz: 231e6a4c4c146c76cd4b34387070ab26e3574be16a8fca2f8857fe90550e6cd50d39b7dfa0a75a07eead3f3c41c2a252e70b0bf70456bb01969388099310fdbe
7
+ data.tar.gz: afbe311e75325a4cac5843be88b84ffd6c122e47deadd116f39d6221673a4306b422179526b46fbea14a9c47c944e8dc4fa57095c311ba49b7aa70fe3a5c7e84
checksums.yaml.gz.sig ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,33 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.5
3
+ Exclude:
4
+ - '**/Guardfile'
5
+ - 'db/**/*'
6
+ - 'tmp/**/*'
7
+ - 'vendor/**/*'
8
+ - 'bin/**/*'
9
+ - 'log/**/*'
10
+ - 'dotloop.gemspec'
11
+ Documentation:
12
+ Enabled: false
13
+ Metrics/BlockLength:
14
+ Max: 100
15
+ Exclude:
16
+ - 'spec/**/*.rb'
17
+ Metrics/LineLength:
18
+ Max: 120
19
+ AllowURI: true
20
+ URISchemes:
21
+ - http
22
+ - https
23
+ Metrics/MethodLength:
24
+ CountComments: false
25
+ Max: 15
26
+ Style/RaiseArgs:
27
+ Enabled: false
28
+ Style/ClassAndModuleChildren:
29
+ Enabled: false
30
+ Style/FrozenStringLiteralComment:
31
+ Enabled: false
32
+ Style/Alias:
33
+ EnforcedStyle: prefer_alias_method
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at shane.davies@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in docusign_dtr.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Loft 47
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # DocusignDtr
2
+ This library is designed to help ruby applications consume the Docusign DTR API.
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'docusign_dtr'
10
+ ```
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install docusign_dtr
19
+
20
+ ## Usage
21
+
22
+ ```ruby
23
+ auth = DocusignDtr::Auth::Jwt.new(
24
+ integrator_key: '1e1e1e1e-1e1e-1e1e-1e1e-1e1e1e1e1e1e',
25
+ private_key: "-----BEGIN RSA PRIVATE KEY-----\nTRUST_NO_ONE\n-----END RSA PRIVATE KEY-----",
26
+ user_guid: '1f1f1f1f-1f1f-1f1f-1f1f-1f1f1f1f1f1f',
27
+ redirect_uri: 'https://www.google.com'
28
+ )
29
+ begin
30
+ auth.request_token
31
+ rescue DocusignDtr::ConsentRequired
32
+ # launch or redirect user to grant url and try again
33
+ Launchy.open(auth.grant_url)
34
+ end
35
+
36
+ puts "Your access token is #{auth.access_token}"
37
+ ```
38
+ Now you can use the ```access_token``` in the docusign [api explorer](https://stage.cartavi.com/restapi/swashbuckle/ui/index).
39
+
40
+ When you receive a DocusignDtr::ConsentRequired error Send your client to the grant_url above and they will be required to authenticate your app. Once they authorize your app they will be redirected to the redirect_url (for now its google.com)
41
+ When you receive an auth object you can use the access_token to connect to resources:
42
+
43
+ ```ruby
44
+ auth_token = 'SOME_LONG_SECRET_TRUST_NO_ONE_WITH_THIS'
45
+ client = DocusignDtr::Client.new(token: auth_token, test_mode: false, application: 'myapplication.com')
46
+ all_rooms = client.Room.all # => [#<DocusignDtr::Models::Room ... >,]
47
+ room = client.Room.find(all_rooms.last.id) # => #<DocusignDtr::Models::Room ... >
48
+ room.name #=> My Room
49
+ document = room.documents.last # => #<DocusignDtr::Models::Docuement ... >
50
+ file = document.download # => #<File:/tmp/....>
51
+
52
+ # Other endpoints
53
+ offices = client.Office.all
54
+ document = client.Document.find(12345)
55
+ member = client.Member.find(56789)
56
+ task_list = client.TaskList.find(98765)
57
+ titles = client.Title.all
58
+ profile = client.User.profile(54321)
59
+ ```
60
+
61
+ ## Development
62
+
63
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
64
+
65
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
66
+
67
+ ## Contributing
68
+
69
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/docusign_dtr.
70
+
71
+ ## License
72
+
73
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "docusign_dtr"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "pry"
14
+ Pry.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhzZGF2
3
+ aWVzL0RDPWxvZnQ0Ny9EQz1jb20wHhcNMTgwODA5MjA0NjQ5WhcNMTkwODA5MjA0
4
+ NjQ5WjAjMSEwHwYDVQQDDBhzZGF2aWVzL0RDPWxvZnQ0Ny9EQz1jb20wggGiMA0G
5
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC5uLNdd1ksckPgS7YfXj+6CWuxA8K5
6
+ hDLOp9warlWizDgG3G4gyC6IwPatQX2cJACkArsB/pgdrmHf8scTGrCpFxwdMBZ1
7
+ /PdNFjtyosnolsCP1wtjUI3AZcUkDXMpZhBAu6ouCNoZlqhzTtWzDFLDsyTgq+Dh
8
+ J92jh3e30mxm9SUk9oU2OG7S1Z2LyjHmKFVYQVKv23hcEzccyuzicKFFMsgQw8Wp
9
+ Mnm+sU/bas7L3FYKHoqoRhM3fnwfPrk1bh/o8xgdKcZJovF6Tyu1S1g/02zPJL5L
10
+ SwlclupuM4t4jkvG3s4L/wuOcFN34nYG4XvpHug0C13R0soZnfPCpQvBYOGOPlol
11
+ KoIPL74jre7R9xPR2ww/RQy0Jt6L9x8l+Ob4wVH86Ybj31Ht9JM4sdGSVLT8cM7I
12
+ CJXmr4Y+TMXUjt8E1a8AWIO0KPB7bEzQji3ap7nr5YPx8Gf1fSP4rKHmUmnWwM6h
13
+ 21Ml2EfZZvYiMnXRwwRRI4UxagABBYr+SgMCAwEAAaN3MHUwCQYDVR0TBAIwADAL
14
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFL6k7vksZaFGNcJSoOHYm7Mrft0kMB0GA1Ud
15
+ EQQWMBSBEnNkYXZpZXNAbG9mdDQ3LmNvbTAdBgNVHRIEFjAUgRJzZGF2aWVzQGxv
16
+ ZnQ0Ny5jb20wDQYJKoZIhvcNAQELBQADggGBAHAZ7y+8cRxZN5IVj1QLNKUpq0jz
17
+ rlXdw5LkX1RHAF+AGx04epkfd98Rb89Pw8UPl15KwpnBqLP0Edvdc0cQ2f+MuRod
18
+ q0b9RdxeaafJiKz63W5xE+U5ISZZMx+Kwkp9Y+LVl+eJR2jI/bE15ZopFw9Zl9NV
19
+ NW5L0VAFfOx5MTwpQI3gevlbH+cQpAT/97mnIHsKU5fbHeY4cn4QtzycekPDl8oB
20
+ UG5uO7+0xHrKOlKYBGjCMejj/NFanOVw6tXJAURjoHMOK8W4Q9rLuJIiI0WFZxOP
21
+ Ojo1ihgcp2Dgjr5QJ6QayOb4Y4j2r8RrkSvPL04tPXE8Oj0j0/yV4PZin/odJ9LN
22
+ ROe6I8zgZ08i2nLTiHsdilC+eEez2Gxl3TVbavPUEKocGUi1l6tr+PBjUb0bNKGv
23
+ WPTyTwBv5qAL48mT3OBIV99mY13XurTi2s2OCJAgkQZIQlGsFzmT/4IDYivCoABO
24
+ QVWtuf6LfMkXYW5shBsTlpiGbXeVlm0QW2Av3w==
25
+ -----END CERTIFICATE-----
@@ -0,0 +1,41 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'docusign_dtr/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'docusign_dtr'
7
+ spec.version = DocusignDtr::VERSION
8
+ spec.authors = ['Loft47']
9
+ spec.email = ['support@loft47.com']
10
+
11
+ spec.summary = %(Docusign DTR library)
12
+ spec.description = %(Ruby library for Docusign DTR rest API)
13
+ spec.homepage = %(http://github.com/Loft47/docusign_dtr)
14
+ spec.license = 'MIT'
15
+ spec.cert_chain = ['certs/shanedavies.pem']
16
+ spec.signing_key = File.expand_path('~/.ssh/docusign-private_key.pem') if $PROGRAM_NAME.end_with?('gem')
17
+ spec.required_ruby_version = '~> 2.5'
18
+
19
+ raise 'RubyGems 2.5 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
21
+
22
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ spec.bindir = 'exe'
24
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ['lib']
26
+
27
+ spec.add_runtime_dependency 'httparty'
28
+ spec.add_runtime_dependency 'jwt'
29
+ spec.add_runtime_dependency 'plissken'
30
+ spec.add_runtime_dependency 'virtus'
31
+ spec.add_development_dependency 'bundler'
32
+ spec.add_development_dependency 'byebug'
33
+ spec.add_development_dependency 'launchy'
34
+ spec.add_development_dependency 'pry'
35
+ spec.add_development_dependency 'rake'
36
+ spec.add_development_dependency 'rspec'
37
+ spec.add_development_dependency 'rubocop'
38
+ spec.add_development_dependency 'simplecov'
39
+ spec.add_development_dependency 'travis'
40
+ spec.add_development_dependency 'webmock'
41
+ end
@@ -0,0 +1,17 @@
1
+ module DocusignDtr
2
+ class Activity
3
+ attr_accessor :client
4
+
5
+ def initialize(client:)
6
+ @client = client
7
+ end
8
+
9
+ def all_by_task_id(task_id)
10
+ @client.get("/tasks/#{task_id}/activity")['activity'].map do |activity_attrs|
11
+ activity = DocusignDtr::Models::Activity.new(activity_attrs)
12
+ activity.client = client
13
+ activity
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,87 @@
1
+ require 'uri'
2
+ require 'base64'
3
+ module DocusignDtr
4
+ module Auth
5
+ class Base
6
+ include HTTParty
7
+
8
+ attr_accessor :config
9
+ attr_accessor :token_response
10
+
11
+ def initialize
12
+ @config = DocusignDtr::Models::AuthConfig.new
13
+ end
14
+
15
+ def grant_url
16
+ grant_uri = URI("#{base_uri}oauth/auth")
17
+ grant_uri.query = URI.encode_www_form(grant_params)
18
+ grant_uri.to_s
19
+ end
20
+
21
+ def parse_url_response(url)
22
+ params = URI.decode_www_form(URI(url).query)
23
+ hash = Hash[*params.flatten]
24
+ OpenStruct.new(hash)
25
+ end
26
+
27
+ private
28
+
29
+ def full_scope
30
+ (%w[signature impersonation] + DocusignDtr::DTR_SCOPE).join(' ')
31
+ end
32
+
33
+ def base_uri
34
+ "https://#{domain}/"
35
+ end
36
+
37
+ def domain
38
+ @config.test_mode ? 'account-d.docusign.com' : 'account.docusign.com'
39
+ end
40
+
41
+ def auth_uri
42
+ @auth_uri ||= URI("#{base_uri}oauth/token")
43
+ end
44
+
45
+ def grant_params
46
+ {
47
+ response_type: :code,
48
+ scope: full_scope,
49
+ state: @config.state,
50
+ client_id: @config.integrator_key,
51
+ redirect_uri: @config.redirect_uri
52
+ }.delete_if { |_, v| v.nil? }
53
+ end
54
+
55
+ def base_headers
56
+ {
57
+ 'Content-Type': 'application/x-www-form-urlencoded',
58
+ 'User-Agent': @config.application.to_s,
59
+ 'Accept': '*/*'
60
+ }
61
+ end
62
+
63
+ def encoded_integrator_key
64
+ Base64.urlsafe_encode64("#{@config.integrator_key}:#{@config.secret_key}")
65
+ end
66
+
67
+ def handle_error(response)
68
+ raise error_type(response), "Error communicating: Response code #{response.code}"
69
+ end
70
+
71
+ def error_type(response)
72
+ case response.code
73
+ when 400
74
+ # {"error":"invalid_grant"}
75
+ return DocusignDtr::InvalidGrant if response.parsed_response['error'].match?(/grant/)
76
+ DocusignDtr::ConsentRequired # {"error":"consent_required"}
77
+ when 401
78
+ DocusignDtr::Unauthorized
79
+ when 403
80
+ DocusignDtr::Forbidden
81
+ else
82
+ StandardError
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,43 @@
1
+ require 'securerandom'
2
+ module DocusignDtr
3
+ module Auth
4
+ class Code < Base
5
+ def initialize(integrator_key:,
6
+ secret_key:,
7
+ redirect_uri:,
8
+ test_mode: true,
9
+ application: 'docusign_dtr')
10
+ @config = DocusignDtr::Models::AuthConfig.new(
11
+ application: application,
12
+ integrator_key: integrator_key,
13
+ redirect_uri: redirect_uri,
14
+ secret_key: secret_key,
15
+ state: SecureRandom.uuid,
16
+ test_mode: test_mode
17
+ )
18
+ end
19
+
20
+ def request_token(code:, state: nil)
21
+ raise 'State does ont match. Possible CSRF!' if state && state != @config.state
22
+ params = { grant_type: :authorization_code, code: code }
23
+ response = self.class.post(auth_uri, query: params, headers: headers, timeout: 60)
24
+ handle_error(response.code) if response.code != 200
25
+ @token_response = DocusignDtr::Models::AuthTokenResponse.new(response.parsed_response)
26
+ end
27
+
28
+ def refresh_token
29
+ raise 'No token to refresh' unless @token_response&.access_token
30
+ params = { grant_type: :refresh_token, refresh_token: @token_response.access_token }
31
+ response = self.class.post("#{base_uri}oauth/token", query: params, headers: headers, timeout: 60)
32
+ handle_error(response.code) if response.code != 200
33
+ @token_response = DocusignDtr::Models::AuthTokenResponse.new(response.parsed_response)
34
+ end
35
+
36
+ private
37
+
38
+ def headers
39
+ base_headers.merge('Authorization': "Basic #{encoded_integrator_key}")
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ require 'jwt'
2
+ module DocusignDtr
3
+ module Auth
4
+ class Jwt < Base
5
+ EXPIRES_IN = 3600
6
+ # rubocop:disable Metrics/ParameterLists
7
+ def initialize(integrator_key:,
8
+ private_key:,
9
+ user_guid:,
10
+ redirect_uri:,
11
+ test_mode: true,
12
+ application: 'docusign_dtr')
13
+ @config = DocusignDtr::Models::AuthConfig.new(
14
+ application: application,
15
+ integrator_key: integrator_key,
16
+ private_key: OpenSSL::PKey::RSA.new(private_key),
17
+ redirect_uri: redirect_uri,
18
+ test_mode: test_mode,
19
+ user_guid: user_guid
20
+ )
21
+ end
22
+ # rubocop:enable Metrics/ParameterLists
23
+
24
+ def request_token
25
+ response = self.class.post(auth_uri, query: access_token_params, headers: base_headers, timeout: 60)
26
+ handle_error(response) if response.code != 200
27
+ @token_response = DocusignDtr::Models::AuthTokenResponse.new(response.parsed_response)
28
+ end
29
+
30
+ private
31
+
32
+ def body_params
33
+ {
34
+ iss: @config.integrator_key,
35
+ sub: @config.user_guid,
36
+ aud: domain,
37
+ iat: Time.now.to_i,
38
+ exp: Time.now.to_i + EXPIRES_IN,
39
+ scope: full_scope
40
+ }
41
+ end
42
+
43
+ def access_token_params
44
+ {
45
+ grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
46
+ assertion: JWT.encode(body_params, @config.private_key, 'RS256')
47
+ }
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,98 @@
1
+ module DocusignDtr
2
+ class Client
3
+ include HTTParty
4
+ attr_accessor :token
5
+
6
+ def initialize(token:, test_mode: true, application: 'docusign_dtr')
7
+ @test_mode = test_mode
8
+ @token = token
9
+ @application = application
10
+ raise 'Missing Token' unless token
11
+ end
12
+
13
+ def get(page, params = {})
14
+ response = raw(page, params)
15
+ snakify(response)
16
+ end
17
+
18
+ def raw(page, params = {})
19
+ full_path = [base_uri, page].join
20
+ response = self.class.get(full_path, query: params, headers: headers, timeout: 60)
21
+ handle_error(response.code) if response.code != 200
22
+ response.parsed_response
23
+ end
24
+
25
+ def handle_error(response_code)
26
+ raise error_type(response_code), "Error communicating: Response code #{response_code}"
27
+ end
28
+
29
+ def Office # rubocop:disable Naming/MethodName
30
+ @office ||= DocusignDtr::Office.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
31
+ end
32
+
33
+ def Document # rubocop:disable Naming/MethodName
34
+ @document ||= DocusignDtr::Document.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
35
+ end
36
+
37
+ def Member # rubocop:disable Naming/MethodName
38
+ @member ||= DocusignDtr::Member.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
39
+ end
40
+
41
+ def Meta # rubocop:disable Naming/MethodName
42
+ @meta ||= DocusignDtr::Meta.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
43
+ end
44
+
45
+ def Room # rubocop:disable Naming/MethodName
46
+ @room ||= DocusignDtr::Room.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
47
+ end
48
+
49
+ def Task # rubocop:disable Naming/MethodName
50
+ @task ||= DocusignDtr::Task.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
51
+ end
52
+
53
+ def TaskList # rubocop:disable Naming/MethodName
54
+ @task_list ||= DocusignDtr::TaskList.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
55
+ end
56
+
57
+ def Title # rubocop:disable Naming/MethodName
58
+ @title ||= DocusignDtr::Title.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
59
+ end
60
+
61
+ def User # rubocop:disable Naming/MethodName
62
+ @user ||= DocusignDtr::User.new(client: self) # rubocop:disable Naming/MemoizedInstanceVariableName
63
+ end
64
+
65
+ def base_uri
66
+ @base_uri ||= @test_mode ? 'https://stage.cartavi.com/restapi/v1' : 'https://cartavi.com/restapi/v1'
67
+ end
68
+
69
+ private
70
+
71
+ def headers
72
+ {
73
+ 'Authorization': "Bearer #{@token}",
74
+ 'User-Agent': @application.to_s,
75
+ 'Accept': 'application/json'
76
+ }
77
+ end
78
+
79
+ def snakify(hash)
80
+ if hash.is_a? Array
81
+ hash.map(&:to_snake_keys)
82
+ else
83
+ hash.to_snake_keys
84
+ end
85
+ end
86
+
87
+ def error_type(response_code)
88
+ case response_code
89
+ when 401
90
+ DocusignDtr::Unauthorized
91
+ when 403
92
+ DocusignDtr::Forbidden
93
+ else
94
+ StandardError
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,34 @@
1
+ module DocusignDtr
2
+ class Document
3
+ attr_accessor :client
4
+
5
+ def initialize(client:)
6
+ @client = client
7
+ end
8
+
9
+ def all_by_room_id(room_id)
10
+ @client.get("/rooms/#{room_id}/documents")['documents'].map do |document_attrs|
11
+ document = DocusignDtr::Models::Document.new(document_attrs)
12
+ document.client = client
13
+ document
14
+ end
15
+ end
16
+
17
+ def find(id)
18
+ document_attrs = @client.get("/documents/#{id}/details")
19
+ document = DocusignDtr::Models::Document.new(document_attrs)
20
+ document.client = client
21
+ document
22
+ end
23
+
24
+ def create(document_attrs = {}) end
25
+
26
+ def download(id)
27
+ # document_attrs = @client.get("/documents/#{id}")
28
+ end
29
+
30
+ def destroy(id) end
31
+
32
+ def update(id) end
33
+ end
34
+ end
@@ -0,0 +1,6 @@
1
+ module DocusignDtr
2
+ class ConsentRequired < StandardError; end
3
+ class InvalidGrant < StandardError; end
4
+ class Forbidden < StandardError; end
5
+ class Unauthorized < StandardError; end
6
+ end