authensure 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6d146da491c0a18038f9afd386e8619e76c8a8428a416a2d8e41c24229296134
4
+ data.tar.gz: a887fbe309338a80b927202d8219cf39d44e7cab0a48c8e8c31d9deb5261bacc
5
+ SHA512:
6
+ metadata.gz: 8ab836a8d17e538a691cd90b563b271c17c00a0fd930b54d9802f25bec46e543294bc47d085d9cba48edc6362f63757222c381b5b62f8eaf4e05f0568d6fa56f
7
+ data.tar.gz: bea6f9edb526acb83a69b8afbf279d7b35c193fdef9e703439d279e03f41c9b9d9e9fa21b85fa67b3c538deca311f1421147887086ec047c10c9e2e4031a162f
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,75 @@
1
+ # Contributing to Authensure Ruby SDK
2
+
3
+ Thank you for your interest in contributing to the Authensure Ruby SDK!
4
+
5
+ ## Getting Started
6
+
7
+ 1. Fork the repository
8
+ 2. Clone your fork:
9
+ ```bash
10
+ git clone https://github.com/YOUR_USERNAME/authensure-ruby.git
11
+ cd authensure-ruby
12
+ ```
13
+ 3. Install dependencies:
14
+ ```bash
15
+ bundle install
16
+ ```
17
+ 4. Run tests:
18
+ ```bash
19
+ bundle exec rspec
20
+ ```
21
+
22
+ ## Development Workflow
23
+
24
+ 1. Create a feature branch:
25
+ ```bash
26
+ git checkout -b feature/your-feature-name
27
+ ```
28
+
29
+ 2. Make your changes following the code style guidelines
30
+
31
+ 3. Write tests for your changes
32
+
33
+ 4. Run the test suite:
34
+ ```bash
35
+ bundle exec rspec
36
+ ```
37
+
38
+ 5. Run the linter:
39
+ ```bash
40
+ bundle exec rubocop
41
+ ```
42
+
43
+ 6. Commit your changes:
44
+ ```bash
45
+ git commit -m "feat: Add your feature description"
46
+ ```
47
+
48
+ 7. Push and create a Pull Request
49
+
50
+ ## Code Style
51
+
52
+ - Follow the Ruby Style Guide
53
+ - Use RuboCop for linting
54
+ - Write YARD documentation for public methods
55
+ - Use `frozen_string_literal: true` in all files
56
+
57
+ ## Testing
58
+
59
+ - Write RSpec tests for all new functionality
60
+ - Use WebMock for HTTP stubbing
61
+ - Aim for high test coverage
62
+
63
+ ## Commit Messages
64
+
65
+ Use conventional commits:
66
+ - `feat:` New feature
67
+ - `fix:` Bug fix
68
+ - `docs:` Documentation
69
+ - `test:` Tests
70
+ - `refactor:` Refactoring
71
+ - `chore:` Maintenance
72
+
73
+ ## License
74
+
75
+ By contributing, you agree that your contributions will be licensed under the MIT License.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Authensure
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,274 @@
1
+ # Authensure Ruby SDK
2
+
3
+ [![Gem Version](https://img.shields.io/gem/v/authensure)](https://rubygems.org/gems/authensure)
4
+ [![Ruby Version](https://img.shields.io/badge/ruby-%3E%3D%203.0-ruby.svg)](https://www.ruby-lang.org/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ Official Ruby SDK for [Authensure](https://authensure.app) - the electronic signature and document authentication platform.
8
+
9
+ ## Features
10
+
11
+ - **Full API Coverage** - Access all Authensure API endpoints
12
+ - **Ruby 3.0+** - Modern Ruby with full type annotations via YARD
13
+ - **Automatic Retries** - Built-in exponential backoff for transient errors
14
+ - **Rate Limit Handling** - Automatic rate limit detection and backoff
15
+ - **Webhook Verification** - Easy webhook signature verification
16
+ - **File Uploads** - Simplified document upload handling
17
+ - **Debug Mode** - Detailed logging for development
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'authensure'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ ```bash
30
+ bundle install
31
+ ```
32
+
33
+ Or install it yourself as:
34
+
35
+ ```bash
36
+ gem install authensure
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ```ruby
42
+ require 'authensure'
43
+
44
+ # Initialize with API key
45
+ client = Authensure::Client.new(api_key: 'your_api_key')
46
+
47
+ # Or use class methods
48
+ client = Authensure::Client.with_api_key('your_api_key')
49
+
50
+ # Create an envelope
51
+ envelope = client.envelopes.create(
52
+ name: 'Contract Agreement',
53
+ message: 'Please review and sign this document'
54
+ )
55
+
56
+ puts "Created envelope: #{envelope[:id]}"
57
+ ```
58
+
59
+ ## Configuration
60
+
61
+ ### Global Configuration
62
+
63
+ ```ruby
64
+ Authensure.configure do |config|
65
+ config.api_key = 'your_api_key'
66
+ config.base_url = 'https://api.authensure.app/api' # Optional
67
+ config.timeout = 30 # Optional
68
+ config.retry_attempts = 3 # Optional
69
+ config.debug = false # Optional
70
+ end
71
+
72
+ client = Authensure.client
73
+ ```
74
+
75
+ ### Per-Client Configuration
76
+
77
+ ```ruby
78
+ client = Authensure::Client.new(
79
+ api_key: 'your_api_key',
80
+ base_url: 'https://api.authensure.app/api',
81
+ timeout: 30,
82
+ retry_attempts: 3,
83
+ debug: true
84
+ )
85
+ ```
86
+
87
+ ### Using Access Token
88
+
89
+ ```ruby
90
+ client = Authensure::Client.with_access_token('your_access_token')
91
+ ```
92
+
93
+ ## API Reference
94
+
95
+ ### Envelopes
96
+
97
+ ```ruby
98
+ # List envelopes
99
+ envelopes = client.envelopes.list(status: 'DRAFT')
100
+
101
+ # Get an envelope
102
+ envelope = client.envelopes.get('envelope_id')
103
+
104
+ # Create an envelope
105
+ envelope = client.envelopes.create(name: 'My Contract', message: 'Please sign')
106
+
107
+ # Add a recipient
108
+ recipient = client.envelopes.add_recipient(
109
+ 'envelope_id',
110
+ email: 'signer@example.com',
111
+ name: 'John Doe',
112
+ role: 'signer'
113
+ )
114
+
115
+ # Send for signing
116
+ envelope = client.envelopes.send_envelope('envelope_id')
117
+
118
+ # Void an envelope
119
+ envelope = client.envelopes.void('envelope_id', reason: 'Contract cancelled')
120
+ ```
121
+
122
+ ### Documents
123
+
124
+ ```ruby
125
+ # Upload a document
126
+ document = client.documents.upload(
127
+ envelope_id: 'envelope_id',
128
+ file: File.read('contract.pdf'),
129
+ filename: 'contract.pdf'
130
+ )
131
+
132
+ # Get signed document URL
133
+ result = client.documents.get_signed_url('document_id')
134
+ puts result[:url]
135
+
136
+ # Download a document
137
+ content = client.documents.download('document_id')
138
+ ```
139
+
140
+ ### Templates
141
+
142
+ ```ruby
143
+ # List templates
144
+ templates = client.templates.list
145
+
146
+ # Create from template
147
+ envelope = client.templates.use(
148
+ 'template_id',
149
+ name: 'New Contract',
150
+ recipients: [
151
+ { roleId: 'role_1', email: 'signer@example.com', name: 'John Doe' }
152
+ ]
153
+ )
154
+ ```
155
+
156
+ ### Contacts
157
+
158
+ ```ruby
159
+ # List contacts
160
+ contacts = client.contacts.list(search: 'acme', limit: 20)
161
+
162
+ # Create a contact
163
+ contact = client.contacts.create(
164
+ email: 'contact@example.com',
165
+ name: 'Jane Smith',
166
+ company: 'Acme Inc'
167
+ )
168
+ ```
169
+
170
+ ### Webhooks
171
+
172
+ ```ruby
173
+ # Create a webhook
174
+ webhook = client.webhooks.create(
175
+ url: 'https://your-app.com/webhooks/authensure',
176
+ events: ['envelope.signed', 'envelope.completed']
177
+ )
178
+
179
+ # Verify webhook signature
180
+ is_valid = Authensure::Resources::Webhooks.verify_signature(
181
+ payload,
182
+ signature,
183
+ 'your_webhook_secret'
184
+ )
185
+
186
+ # Construct verified event
187
+ event = Authensure::Resources::Webhooks.construct_event(
188
+ payload,
189
+ signature,
190
+ 'your_webhook_secret'
191
+ )
192
+ puts "Event type: #{event[:event]}"
193
+ ```
194
+
195
+ ## Error Handling
196
+
197
+ ```ruby
198
+ begin
199
+ envelope = client.envelopes.get('invalid_id')
200
+ rescue Authensure::NotFoundError
201
+ puts 'Envelope not found'
202
+ rescue Authensure::AuthenticationError
203
+ puts 'Invalid API key'
204
+ rescue Authensure::RateLimitError => e
205
+ puts "Rate limited, retry after: #{e.retry_after} seconds"
206
+ rescue Authensure::ValidationError => e
207
+ puts "Validation errors: #{e.validation_errors}"
208
+ rescue Authensure::Error => e
209
+ puts "API error: #{e.message} (code: #{e.code})"
210
+ end
211
+ ```
212
+
213
+ ## Rails Integration
214
+
215
+ Add to your `config/initializers/authensure.rb`:
216
+
217
+ ```ruby
218
+ Authensure.configure do |config|
219
+ config.api_key = Rails.application.credentials.authensure_api_key
220
+ config.debug = Rails.env.development?
221
+ end
222
+ ```
223
+
224
+ Use in your controllers:
225
+
226
+ ```ruby
227
+ class EnvelopesController < ApplicationController
228
+ def create
229
+ envelope = authensure_client.envelopes.create(
230
+ name: params[:name],
231
+ message: params[:message]
232
+ )
233
+ render json: envelope
234
+ end
235
+
236
+ private
237
+
238
+ def authensure_client
239
+ @authensure_client ||= Authensure.client
240
+ end
241
+ end
242
+ ```
243
+
244
+ ## Development
245
+
246
+ After checking out the repo:
247
+
248
+ ```bash
249
+ bundle install
250
+ ```
251
+
252
+ Run the tests:
253
+
254
+ ```bash
255
+ bundle exec rspec
256
+ ```
257
+
258
+ Run the linter:
259
+
260
+ ```bash
261
+ bundle exec rubocop
262
+ ```
263
+
264
+ ## Resources
265
+
266
+ - [Documentation](https://authensure.app/docs/sdk/ruby)
267
+ - [API Reference](https://authensure.app/dashboard/developers)
268
+ - [GitHub Repository](https://github.com/Authensure/authensure-ruby)
269
+ - [RubyGems](https://rubygems.org/gems/authensure)
270
+ - [Report Issues](https://github.com/Authensure/authensure-ruby/issues)
271
+
272
+ ## License
273
+
274
+ This gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: %i[spec rubocop]
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/authensure/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "authensure"
7
+ spec.version = Authensure::VERSION
8
+ spec.authors = ["Authensure"]
9
+ spec.email = ["support@authensure.app"]
10
+
11
+ spec.summary = "Official Authensure SDK for Ruby"
12
+ spec.description = "Ruby SDK for Authensure - the electronic signature and document authentication platform. " \
13
+ "Provides a simple interface to create envelopes, manage documents, handle signatures, " \
14
+ "and integrate webhooks."
15
+ spec.homepage = "https://authensure.app"
16
+ spec.license = "MIT"
17
+ spec.required_ruby_version = ">= 3.0.0"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = "https://github.com/Authensure/authensure-ruby"
21
+ spec.metadata["changelog_uri"] = "https://github.com/Authensure/authensure-ruby/blob/main/CHANGELOG.md"
22
+ spec.metadata["documentation_uri"] = "https://authensure.app/docs/sdk/ruby"
23
+ spec.metadata["bug_tracker_uri"] = "https://github.com/Authensure/authensure-ruby/issues"
24
+ spec.metadata["rubygems_mfa_required"] = "true"
25
+
26
+ spec.files = Dir.chdir(__dir__) do
27
+ `git ls-files -z`.split("\x0").reject do |f|
28
+ (File.expand_path(f) == __FILE__) ||
29
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
30
+ end
31
+ end
32
+ spec.bindir = "exe"
33
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
34
+ spec.require_paths = ["lib"]
35
+
36
+ spec.add_dependency "faraday", ">= 1.0", "< 3.0"
37
+ spec.add_dependency "faraday-multipart", "~> 1.0"
38
+ spec.add_dependency "faraday-retry", "~> 2.0"
39
+
40
+ spec.add_development_dependency "bundler", "~> 2.0"
41
+ spec.add_development_dependency "rake", "~> 13.0"
42
+ spec.add_development_dependency "rspec", "~> 3.0"
43
+ spec.add_development_dependency "rubocop", "~> 1.0"
44
+ spec.add_development_dependency "rubocop-rspec", "~> 2.0"
45
+ spec.add_development_dependency "simplecov", "~> 0.22"
46
+ spec.add_development_dependency "webmock", "~> 3.0"
47
+ spec.add_development_dependency "yard", "~> 0.9"
48
+ end
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "authensure"
5
+
6
+ api_key = ENV.fetch("AUTHENSURE_API_KEY", nil)
7
+ unless api_key
8
+ puts "Error: AUTHENSURE_API_KEY environment variable not set"
9
+ puts "Set it with: export AUTHENSURE_API_KEY='your_api_key_here'"
10
+ exit 1
11
+ end
12
+
13
+ client = Authensure::Client.new(api_key: api_key)
14
+
15
+ puts "=== Authensure Ruby SDK Basic Usage ==="
16
+ puts
17
+
18
+ puts "Creating envelope..."
19
+ envelope = client.envelopes.create(
20
+ name: "Contract Agreement",
21
+ message: "Please review and sign this contract at your earliest convenience."
22
+ )
23
+ puts "Created envelope: #{envelope[:id]}"
24
+ puts " Name: #{envelope[:name]}"
25
+ puts " Status: #{envelope[:status]}"
26
+
27
+ puts
28
+ puts "Adding recipient..."
29
+ recipient = client.envelopes.add_recipient(
30
+ envelope[:id],
31
+ email: "signer@example.com",
32
+ name: "John Doe",
33
+ role: "signer"
34
+ )
35
+ puts "Added recipient: #{recipient[:id]}"
36
+ puts " Email: #{recipient[:email]}"
37
+ puts " Name: #{recipient[:name]}"
38
+
39
+ puts
40
+ puts "Fetching envelope details..."
41
+ envelope = client.envelopes.get(envelope[:id])
42
+ puts "Envelope has #{envelope[:recipients]&.length || 0} recipient(s)"
43
+
44
+ puts
45
+ puts "Listing all envelopes..."
46
+ envelopes = client.envelopes.list
47
+ puts "Found #{envelopes.length} envelope(s)"
48
+
49
+ puts
50
+ puts "Cleaning up..."
51
+ client.envelopes.delete(envelope[:id])
52
+ puts "Deleted test envelope"
53
+
54
+ puts
55
+ puts "=== Example Complete ==="
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "authensure"
5
+ require "sinatra"
6
+ require "json"
7
+
8
+ WEBHOOK_SECRET = ENV.fetch("AUTHENSURE_WEBHOOK_SECRET", "")
9
+
10
+ post "/webhooks/authensure" do
11
+ payload = request.body.read
12
+ signature = request.env["HTTP_X_AUTHENSURE_SIGNATURE"] || ""
13
+
14
+ begin
15
+ event = Authensure::Resources::Webhooks.construct_event(payload, signature, WEBHOOK_SECRET)
16
+ rescue Authensure::Error => e
17
+ puts "Webhook signature verification failed: #{e.message}"
18
+ halt 401, { error: "Invalid signature" }.to_json
19
+ end
20
+
21
+ puts "=" * 50
22
+ puts "Received webhook event: #{event[:event]}"
23
+ puts "Timestamp: #{event[:timestamp]}"
24
+ puts "=" * 50
25
+
26
+ case event[:event]
27
+ when "envelope.created"
28
+ puts "Envelope created: #{event[:data]["envelopeId"]}"
29
+ when "envelope.sent"
30
+ puts "Envelope sent: #{event[:data]["envelopeId"]}"
31
+ when "envelope.viewed"
32
+ puts "Envelope viewed by: #{event[:data]["recipientEmail"]}"
33
+ when "envelope.signed"
34
+ puts "Envelope signed by: #{event[:data]["recipientName"]}"
35
+ when "envelope.completed"
36
+ puts "Envelope completed: #{event[:data]["envelopeId"]}"
37
+ when "envelope.declined"
38
+ puts "Envelope declined by: #{event[:data]["recipientEmail"]}"
39
+ puts "Reason: #{event[:data]["declineReason"]}"
40
+ when "envelope.voided"
41
+ puts "Envelope voided: #{event[:data]["envelopeId"]}"
42
+ else
43
+ puts "Unhandled event type: #{event[:event]}"
44
+ puts "Data: #{JSON.pretty_generate(event[:data])}"
45
+ end
46
+
47
+ { received: true }.to_json
48
+ end
49
+
50
+ get "/health" do
51
+ { status: "healthy" }.to_json
52
+ end
53
+
54
+ if __FILE__ == $PROGRAM_NAME
55
+ puts "Starting Authensure webhook server..."
56
+ puts "Listening on: http://localhost:4567/webhooks/authensure"
57
+ puts "Health check: http://localhost:4567/health"
58
+ puts
59
+ puts "Warning: AUTHENSURE_WEBHOOK_SECRET not set" if WEBHOOK_SECRET.empty?
60
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authensure
4
+ class Client
5
+ attr_reader :config, :http
6
+
7
+ def initialize(options = {})
8
+ @config = build_config(options)
9
+ @http = HttpClient.new(@config)
10
+ end
11
+
12
+ def auth
13
+ @auth ||= Resources::Auth.new(@http)
14
+ end
15
+
16
+ def envelopes
17
+ @envelopes ||= Resources::Envelopes.new(@http)
18
+ end
19
+
20
+ def documents
21
+ @documents ||= Resources::Documents.new(@http)
22
+ end
23
+
24
+ def templates
25
+ @templates ||= Resources::Templates.new(@http)
26
+ end
27
+
28
+ def contacts
29
+ @contacts ||= Resources::Contacts.new(@http)
30
+ end
31
+
32
+ def webhooks
33
+ @webhooks ||= Resources::Webhooks.new(@http)
34
+ end
35
+
36
+ def users
37
+ @users ||= Resources::Users.new(@http)
38
+ end
39
+
40
+ def organizations
41
+ @organizations ||= Resources::Organizations.new(@http)
42
+ end
43
+
44
+ def api_keys
45
+ @api_keys ||= Resources::ApiKeys.new(@http)
46
+ end
47
+
48
+ def teams
49
+ @teams ||= Resources::Teams.new(@http)
50
+ end
51
+
52
+ def signatures
53
+ @signatures ||= Resources::Signatures.new(@http)
54
+ end
55
+
56
+ def self.with_api_key(api_key, **options)
57
+ new(options.merge(api_key: api_key))
58
+ end
59
+
60
+ def self.with_access_token(access_token, **options)
61
+ new(options.merge(access_token: access_token))
62
+ end
63
+
64
+ private
65
+
66
+ def build_config(options)
67
+ config = Configuration.new
68
+ config.api_key = options[:api_key] if options[:api_key]
69
+ config.access_token = options[:access_token] if options[:access_token]
70
+ config.base_url = options[:base_url] if options[:base_url]
71
+ config.timeout = options[:timeout] if options[:timeout]
72
+ config.retry_attempts = options[:retry_attempts] if options[:retry_attempts]
73
+ config.retry_delay = options[:retry_delay] if options[:retry_delay]
74
+ config.debug = options[:debug] if options.key?(:debug)
75
+ config
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authensure
4
+ class Configuration
5
+ attr_accessor :api_key, :access_token, :base_url, :timeout, :retry_attempts, :retry_delay, :debug
6
+
7
+ DEFAULT_BASE_URL = "https://api.authensure.app/api"
8
+ DEFAULT_TIMEOUT = 30
9
+ DEFAULT_RETRY_ATTEMPTS = 3
10
+ DEFAULT_RETRY_DELAY = 1
11
+
12
+ def initialize
13
+ @api_key = ENV.fetch("AUTHENSURE_API_KEY", nil)
14
+ @access_token = nil
15
+ @base_url = ENV.fetch("AUTHENSURE_BASE_URL", DEFAULT_BASE_URL)
16
+ @timeout = DEFAULT_TIMEOUT
17
+ @retry_attempts = DEFAULT_RETRY_ATTEMPTS
18
+ @retry_delay = DEFAULT_RETRY_DELAY
19
+ @debug = false
20
+ end
21
+ end
22
+ end