signatory 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rvmrc +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +42 -0
- data/History.txt +4 -0
- data/README.rdoc +96 -0
- data/Rakefile +12 -0
- data/lib/signatory/api/base.rb +43 -0
- data/lib/signatory/api/connection.rb +14 -0
- data/lib/signatory/credentials.rb +35 -0
- data/lib/signatory/document.rb +12 -0
- data/lib/signatory/legacy_active_resource_hacks.rb +37 -0
- data/lib/signatory/merge_field.rb +28 -0
- data/lib/signatory/recipient.rb +24 -0
- data/lib/signatory/role.rb +27 -0
- data/lib/signatory/ruby_hacks.rb +7 -0
- data/lib/signatory/template.rb +43 -0
- data/lib/signatory/version.rb +3 -0
- data/lib/signatory.rb +36 -0
- data/signatory.gemspec +28 -0
- data/spec/credentials_spec.rb +39 -0
- data/spec/document_spec.rb +35 -0
- data/spec/fixtures/document.xml.erb +51 -0
- data/spec/fixtures/documents.xml.erb +49 -0
- data/spec/fixtures/template.xml.erb +32 -0
- data/spec/fixtures/template_prepackage.xml.erb +28 -0
- data/spec/fixtures/template_sent.xml.erb +4 -0
- data/spec/fixtures/templates.xml.erb +13 -0
- data/spec/helpers/right_signature_stub.rb +81 -0
- data/spec/merge_field_spec.rb +25 -0
- data/spec/recipient_spec.rb +47 -0
- data/spec/role_spec.rb +25 -0
- data/spec/signatory_spec.rb +32 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/template_spec.rb +79 -0
- metadata +201 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create --install ruby-1.9.2@signatory
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
signatory (0.0.2)
|
5
|
+
activeresource (>= 2.3.9)
|
6
|
+
bundler (= 1.0.0)
|
7
|
+
oauth (= 0.4.3)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activeresource (2.3.9)
|
13
|
+
activesupport (= 2.3.9)
|
14
|
+
activesupport (2.3.9)
|
15
|
+
addressable (2.2.1)
|
16
|
+
crack (0.1.8)
|
17
|
+
diff-lcs (1.1.2)
|
18
|
+
oauth (0.4.3)
|
19
|
+
rspec (2.0.0.beta.22)
|
20
|
+
rspec-core (= 2.0.0.beta.22)
|
21
|
+
rspec-expectations (= 2.0.0.beta.22)
|
22
|
+
rspec-mocks (= 2.0.0.beta.22)
|
23
|
+
rspec-core (2.0.0.beta.22)
|
24
|
+
rspec-expectations (2.0.0.beta.22)
|
25
|
+
diff-lcs (>= 1.1.2)
|
26
|
+
rspec-mocks (2.0.0.beta.22)
|
27
|
+
rspec-core (= 2.0.0.beta.22)
|
28
|
+
rspec-expectations (= 2.0.0.beta.22)
|
29
|
+
webmock (1.3.5)
|
30
|
+
addressable (>= 2.1.1)
|
31
|
+
crack (>= 0.1.7)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
ruby
|
35
|
+
|
36
|
+
DEPENDENCIES
|
37
|
+
activeresource (>= 2.3.9)
|
38
|
+
bundler (= 1.0.0)
|
39
|
+
oauth (= 0.4.3)
|
40
|
+
rspec (= 2.0.0.beta.22)
|
41
|
+
signatory!
|
42
|
+
webmock (= 1.3.5)
|
data/History.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
= signatory
|
2
|
+
|
3
|
+
* http://github.com/profounder/signatory
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
A library to simplify interactions with the RightSignature API. One of the primary goals of this library is to make the workflow clear to developers for using some of the more interesting features of the RightSignature system, eg: templates, document merges, and embedded signature frames.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* FIX (list of features or problems)
|
12
|
+
|
13
|
+
== SYNOPSIS:
|
14
|
+
|
15
|
+
cred = Signatory::Credentials.load(File.open('rs.yml'))
|
16
|
+
if cred.oauth_ready? # true if access token is provided by the credential file otherwise false
|
17
|
+
# if you don't need to handle the credentials separately you can pass
|
18
|
+
# something that Signatory:Credentials can load (hash or file) instead
|
19
|
+
Signatory.credentials = cred
|
20
|
+
|
21
|
+
Signatory::Document.all # => List all documents
|
22
|
+
doc = Signatory::Document.find('XXXXXXXXXXX') # => Get document by id
|
23
|
+
|
24
|
+
...
|
25
|
+
|
26
|
+
Signatory::Template.all # => List all templates
|
27
|
+
template = Signatory::Template.find('XXXXXXXXX') # => Get a template by id
|
28
|
+
|
29
|
+
merge_fields = [
|
30
|
+
Signatory::MergeField.new(:name => "Company Name", :value => "ABC Corp."),
|
31
|
+
Signatory::MergeField.new(:name => "Percentage", :value => "5.8%"),
|
32
|
+
Signatory::MergeField.new(:name => "Term", :value => "48 months"),
|
33
|
+
Signatory::MergeField.new(:name => "Monthly Payback", :value => "$30.00")
|
34
|
+
]
|
35
|
+
|
36
|
+
# If you aren't embedding then you should include email addresses. You can
|
37
|
+
# also use instances of Signatory::Signer
|
38
|
+
roles = [
|
39
|
+
Signatory::Role.new(:role_name => 'Issuer', :name => 'Ryan Garver'),
|
40
|
+
Signatory::Role.new(:role_name => 'Investor', :name => 'Cary Dunn')
|
41
|
+
]
|
42
|
+
|
43
|
+
doc = template.build_document(merge_fields, roles)
|
44
|
+
|
45
|
+
signer = doc.recipients.first # Order matters. Returns a Signatory::Recipient
|
46
|
+
|
47
|
+
# Can be embedded with:
|
48
|
+
#
|
49
|
+
# <iframe src ="<%= signer.embed_url(redirect_url, :height => 500, :width => 700) %>"
|
50
|
+
# width="700px" height="500px" frameborder="0" scrolling="no">
|
51
|
+
# <p>Your browser does not support iframes.</p>
|
52
|
+
# </iframe>
|
53
|
+
#
|
54
|
+
# or use signer.embed_code(redirect_url, :height => 500, :width => 700) to generate the
|
55
|
+
# above code. This will throw an exception if signer is not associated
|
56
|
+
# with a real document yet.
|
57
|
+
else
|
58
|
+
... begin oauth workflow ...
|
59
|
+
end
|
60
|
+
|
61
|
+
== REQUIREMENTS:
|
62
|
+
|
63
|
+
* FIX (list of requirements)
|
64
|
+
|
65
|
+
== INSTALL:
|
66
|
+
|
67
|
+
* FIX (sudo gem install, anything else)
|
68
|
+
|
69
|
+
== THANKS:
|
70
|
+
|
71
|
+
Special thanks to Cary Dunn at RightSignature for putting together a sample Rails app that formulated how the API should be used and introduced the embedded signing frame.
|
72
|
+
|
73
|
+
== LICENSE:
|
74
|
+
|
75
|
+
(The MIT License)
|
76
|
+
|
77
|
+
Copyright (c) 2010 Ryan Garver
|
78
|
+
|
79
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
80
|
+
a copy of this software and associated documentation files (the
|
81
|
+
'Software'), to deal in the Software without restriction, including
|
82
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
83
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
84
|
+
permit persons to whom the Software is furnished to do so, subject to
|
85
|
+
the following conditions:
|
86
|
+
|
87
|
+
The above copyright notice and this permission notice shall be
|
88
|
+
included in all copies or substantial portions of the Software.
|
89
|
+
|
90
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
91
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
92
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
93
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
94
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
95
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
96
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubygems/specification'
|
5
|
+
require 'bundler'
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
RSpec::Core::RakeTask.new do |t|
|
9
|
+
t.rspec_opts = ['--colour', '--format', 'progress']
|
10
|
+
end
|
11
|
+
|
12
|
+
task :default => :spec
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Signatory
|
2
|
+
module API
|
3
|
+
class Base < ActiveResource::Base
|
4
|
+
self.site = 'https://rightsignature.com/api/'
|
5
|
+
|
6
|
+
def id
|
7
|
+
guid
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def instantiate_collection(collection, opts)
|
12
|
+
if collection.has_key?(formatted_collection_name)
|
13
|
+
collection = collection[formatted_collection_name]
|
14
|
+
end
|
15
|
+
super([collection[formatted_name]].flatten, opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
def formatted_name
|
19
|
+
self.name.split('::').last.downcase
|
20
|
+
end
|
21
|
+
|
22
|
+
def formatted_collection_name
|
23
|
+
self.name.split('::').last.downcase.pluralize
|
24
|
+
end
|
25
|
+
|
26
|
+
def connection(refresh = false)
|
27
|
+
if defined?(@connection) || superclass == Object
|
28
|
+
@connection = Signatory::API::Connection.new(site, format) if refresh || @connection.nil?
|
29
|
+
@connection.proxy = proxy if proxy
|
30
|
+
@connection.user = user if user
|
31
|
+
@connection.password = password if password
|
32
|
+
@connection.auth_type = auth_type if auth_type
|
33
|
+
@connection.timeout = timeout if timeout
|
34
|
+
@connection.ssl_options = ssl_options if ssl_options
|
35
|
+
@connection
|
36
|
+
else
|
37
|
+
superclass.connection
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Signatory
|
2
|
+
class Credentials
|
3
|
+
attr_accessor :key, :secret, :access_token, :access_secret
|
4
|
+
|
5
|
+
def initialize(key, secret, access_token, access_secret)
|
6
|
+
@key, @secret, @access_token, @access_secret = key, secret, access_token, access_secret
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.load(source)
|
10
|
+
h = if source.respond_to?(:read)
|
11
|
+
YAML.load(source)
|
12
|
+
elsif source.is_a?(Hash)
|
13
|
+
source.inject({}){ |acc, (k, v)| acc[k.to_s] = v; acc}
|
14
|
+
end
|
15
|
+
|
16
|
+
new(h['key'], h['secret'], h['access_token'], h['access_secret'])
|
17
|
+
end
|
18
|
+
|
19
|
+
def token
|
20
|
+
@consumer ||= OAuth::Consumer.new(key, secret, {
|
21
|
+
:site => 'https://rightsignature.com',
|
22
|
+
:scheme => :header,
|
23
|
+
:http_method => :post,
|
24
|
+
:request_token_path => "/oauth/request_token",
|
25
|
+
:access_token_path => "/oauth/access_token",
|
26
|
+
:authorize_path => "/oauth/authorize"
|
27
|
+
})
|
28
|
+
@token ||= OAuth::AccessToken.new(
|
29
|
+
@consumer,
|
30
|
+
access_token,
|
31
|
+
access_secret
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Signatory
|
2
|
+
class Document < API::Base
|
3
|
+
private
|
4
|
+
def self.instantiate_record(record, opts = {})
|
5
|
+
record['recipients'] = [record['recipients']['recipient']].flatten unless record['recipients'].nil? || record['recipients'].is_a?(Array)
|
6
|
+
|
7
|
+
doc = super(record, opts)
|
8
|
+
doc.recipients.each {|r| r.document = doc } if doc.respond_to?(:recipients)
|
9
|
+
doc
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Signatory
|
2
|
+
module API
|
3
|
+
class Base < ActiveResource::Base
|
4
|
+
|
5
|
+
class << self
|
6
|
+
# This implementation is pulled directly from ActiveResource 3.0.0
|
7
|
+
# http://apidock.com/rails/ActiveResource/Base/all/class
|
8
|
+
def all(*args)
|
9
|
+
find(:all, *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
# ActiveResource < 3.0.0 does not support auth_type
|
13
|
+
def connection(refresh = false)
|
14
|
+
if defined?(@connection) || superclass == Object
|
15
|
+
@connection = Signatory::API::Connection.new(site, format) if refresh || @connection.nil?
|
16
|
+
@connection.proxy = proxy if proxy
|
17
|
+
@connection.user = user if user
|
18
|
+
@connection.password = password if password
|
19
|
+
@connection.timeout = timeout if timeout
|
20
|
+
@connection.ssl_options = ssl_options if ssl_options
|
21
|
+
@connection
|
22
|
+
else
|
23
|
+
superclass.connection
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_xml(options={})
|
29
|
+
fixed_attrs = attributes.clone
|
30
|
+
options[:except].each do |k|
|
31
|
+
fixed_attrs.delete(k.to_s)
|
32
|
+
end
|
33
|
+
fixed_attrs.to_xml({:root => self.class.element_name}.merge(options)){|b| yield(b) if block_given?}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Signatory
|
2
|
+
class MergeField < API::Base
|
3
|
+
def locked
|
4
|
+
attributes['locked'] || true
|
5
|
+
end
|
6
|
+
|
7
|
+
def id; attributes['id']; end
|
8
|
+
|
9
|
+
def to_xml(options = {})
|
10
|
+
identifier = {}
|
11
|
+
identifier.merge!({:merge_field_id => id}) unless attributes['id'].nil?
|
12
|
+
identifier.merge!({:merge_field_name => name}) unless attributes['name'].nil?
|
13
|
+
require 'builder' unless defined? ::Builder
|
14
|
+
options[:indent] ||= 2
|
15
|
+
xml = options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
|
16
|
+
xml.tag!('merge_field', identifier) do
|
17
|
+
if attributes['value'].nil?
|
18
|
+
xml.page page
|
19
|
+
xml.name name
|
20
|
+
xml.id id
|
21
|
+
else
|
22
|
+
xml.value value
|
23
|
+
xml.locked locked
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Signatory
|
2
|
+
class Recipient < API::Base
|
3
|
+
def document=(doc)
|
4
|
+
@document = doc
|
5
|
+
end
|
6
|
+
|
7
|
+
def embed_url(redirect_url, options={})
|
8
|
+
signer_links = @document.get(:signer_links, "redirect_location" => redirect_url)
|
9
|
+
signer = [signer_links['signer_links']['signer_link']].flatten.select do |s|
|
10
|
+
s['role'] == role_id
|
11
|
+
end.first
|
12
|
+
options.merge!(:rt => signer['signer_token'])
|
13
|
+
params = options.sort.map{|k,v| "#{k}=#{v}"}.flatten.join('&')
|
14
|
+
"https://rightsignature.com/signatures/embedded?#{params}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def embed_code(redirect_url, options={})
|
18
|
+
args = ['frameborder="0"', 'scrolling="no"']
|
19
|
+
args << "width=\"#{options[:width]}px\"" if options.has_key?(:width)
|
20
|
+
args << "height=\"#{options[:height]}px\"" if options.has_key?(:height)
|
21
|
+
"<iframe src =\"#{embed_url(redirect_url, options)}\" #{args.join(' ')}><p>Your browser does not support iframes.</p></iframe>"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Signatory
|
2
|
+
class Role < API::Base
|
3
|
+
def email
|
4
|
+
attributes['email'] || 'noemail@rightsignature.com'
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_xml(options = {})
|
8
|
+
identifier = {}
|
9
|
+
identifier.merge!({:role_id => role_id}) unless attributes['role_id'].nil?
|
10
|
+
identifier.merge!({:role_name => role_name}) unless attributes['role_name'].nil?
|
11
|
+
require 'builder' unless defined? ::Builder
|
12
|
+
options[:indent] ||= 2
|
13
|
+
xml = options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
|
14
|
+
xml.role(identifier) do
|
15
|
+
if attributes['name'].nil?
|
16
|
+
xml.tag!('must-sign', must_sign)
|
17
|
+
xml.tag!('document-role-id', document_role_id)
|
18
|
+
xml.role role
|
19
|
+
xml.tag!('is-sender', is_sender)
|
20
|
+
else
|
21
|
+
xml.name name
|
22
|
+
xml.email email
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Signatory
|
2
|
+
class Template < API::Base
|
3
|
+
def prepackage
|
4
|
+
record = connection.format.decode(post(:prepackage).body)
|
5
|
+
Template.instantiate_record(record)
|
6
|
+
end
|
7
|
+
|
8
|
+
def build_document(merge_fields, roles)
|
9
|
+
doc_pkg = prepackage
|
10
|
+
doc_pkg.prefill_and_send(merge_fields, roles)
|
11
|
+
end
|
12
|
+
|
13
|
+
def prefill_and_send(merge_fields, roles)
|
14
|
+
attributes.merge!({
|
15
|
+
'merge_fields' => merge_fields,
|
16
|
+
'roles' => roles,
|
17
|
+
'action' => 'send'
|
18
|
+
})
|
19
|
+
|
20
|
+
doc = connection.format.decode(connection.post("/api/templates.xml", self.to_xml).body)
|
21
|
+
Document.find(doc['guid'])
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_xml(opts = {})
|
25
|
+
super(opts.merge(:dasherize => false, :skip_types => true, :except => [:pages, :_type, :redirect_token, :content_type, :size, :tags])) do |b|
|
26
|
+
b.tag!(:tags) do
|
27
|
+
tags.split(" ").each do |tag|
|
28
|
+
b.tag!(:tag) { b.value tag}
|
29
|
+
end
|
30
|
+
end unless attributes['tags'].blank?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def self.instantiate_record(record, opts = {})
|
36
|
+
record['_type'] = record.delete('type') if record.has_key?('type')
|
37
|
+
record['roles'] = [record['roles']['role']].flatten unless record['roles'].nil? || record['roles'].is_a?(Array)
|
38
|
+
record['merge_fields'] = [record['merge_fields']['merge_field']].flatten unless record['merge_fields'].nil? || record['merge_fields'].is_a?(Array)
|
39
|
+
|
40
|
+
super(record, opts)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/signatory.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'signatory/ruby_hacks'
|
5
|
+
require 'rubygems'
|
6
|
+
require 'bundler/setup'
|
7
|
+
require 'yaml' unless defined?(YAML)
|
8
|
+
require 'oauth' unless defined?(OAuth)
|
9
|
+
require 'active_resource' unless defined?(ActiveResource)
|
10
|
+
|
11
|
+
module Signatory
|
12
|
+
class << self
|
13
|
+
def credentials=(creds)
|
14
|
+
if !creds.is_a?(Credentials)
|
15
|
+
creds = Credentials.load(creds)
|
16
|
+
end
|
17
|
+
@credentials = creds
|
18
|
+
end
|
19
|
+
def credentials; @credentials; end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'signatory/version'
|
24
|
+
require 'signatory/api/connection'
|
25
|
+
require 'signatory/api/base'
|
26
|
+
require 'signatory/credentials'
|
27
|
+
require 'signatory/document'
|
28
|
+
require 'signatory/template'
|
29
|
+
require 'signatory/role'
|
30
|
+
require 'signatory/merge_field'
|
31
|
+
require 'signatory/recipient'
|
32
|
+
|
33
|
+
require 'active_resource/version'
|
34
|
+
if ActiveResource::VERSION::STRING < '3.0.0'
|
35
|
+
require 'signatory/legacy_active_resource_hacks'
|
36
|
+
end
|
data/signatory.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/signatory/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "signatory"
|
6
|
+
s.version = Signatory::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Ryan Garver"]
|
9
|
+
s.email = ["ryan@profounder.com"]
|
10
|
+
s.homepage = "http://rubygems.org/gems/signatory"
|
11
|
+
s.summary = "API wrapper for RightSignature"
|
12
|
+
s.description = "Signatory provides a simple wrapper around the RightSignature API."
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "signatory"
|
16
|
+
|
17
|
+
s.add_development_dependency "bundler", "= 1.0.0"
|
18
|
+
s.add_development_dependency "rspec", "= 2.0.0.beta.22"
|
19
|
+
s.add_development_dependency "webmock", "= 1.3.5"
|
20
|
+
|
21
|
+
s.add_dependency "bundler", "= 1.0.0"
|
22
|
+
s.add_dependency "oauth", "= 0.4.3"
|
23
|
+
s.add_dependency "activeresource", ">= 2.3.9"
|
24
|
+
|
25
|
+
s.files = `git ls-files`.split("\n")
|
26
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
27
|
+
s.require_path = 'lib'
|
28
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Signatory::Credentials do
|
4
|
+
it "loads credentials from yaml" do
|
5
|
+
file = StringIO.new("---\nkey: thekey\nsecret: thesecret\naccess_token: accesstoken\naccess_secret: accesssecret")
|
6
|
+
creds = Signatory::Credentials.load(file)
|
7
|
+
creds.key.should == 'thekey'
|
8
|
+
creds.secret.should == 'thesecret'
|
9
|
+
creds.access_token.should == 'accesstoken'
|
10
|
+
creds.access_secret.should == 'accesssecret'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "loads credentials from hash" do
|
14
|
+
hash = {:key => 'thekey', :secret => 'thesecret', :access_token => 'accesstoken', :access_secret => 'accesssecret'}
|
15
|
+
creds = Signatory::Credentials.load(hash)
|
16
|
+
creds.key.should == 'thekey'
|
17
|
+
creds.secret.should == 'thesecret'
|
18
|
+
creds.access_token.should == 'accesstoken'
|
19
|
+
creds.access_secret.should == 'accesssecret'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "generates an access token from the credentials" do
|
23
|
+
consumer = stub!(:consumer)
|
24
|
+
OAuth::Consumer.should_receive(:new).with('thekey', 'thesecret', {
|
25
|
+
:site => 'https://rightsignature.com',
|
26
|
+
:scheme => :header,
|
27
|
+
:http_method => :post,
|
28
|
+
:request_token_path => "/oauth/request_token",
|
29
|
+
:access_token_path => "/oauth/access_token",
|
30
|
+
:authorize_path => "/oauth/authorize"
|
31
|
+
}).and_return(consumer)
|
32
|
+
access_token = stub!('access_token')
|
33
|
+
OAuth::AccessToken.should_receive(:new).with(consumer, 'accesstoken', 'accesssecret').and_return(access_token)
|
34
|
+
|
35
|
+
hash = {:key => 'thekey', :secret => 'thesecret', :access_token => 'accesstoken', :access_secret => 'accesssecret'}
|
36
|
+
creds = Signatory::Credentials.load(hash)
|
37
|
+
creds.token.should be(access_token)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Signatory::Document do
|
4
|
+
before(:each) do
|
5
|
+
Signatory.credentials = {:key => '123', :secret => '321'}
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".all" do
|
9
|
+
it "returns a list of documents" do
|
10
|
+
stub_documents(:total_documents => 2)
|
11
|
+
documents = Signatory::Document.all
|
12
|
+
documents.count.should == 2
|
13
|
+
documents.each do |doc|
|
14
|
+
doc.should be_a(Signatory::Document)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns the right document" do
|
19
|
+
stub_documents(:total_documents => 1, :documents => [{:subject => 'This is a test', :guid => 'xxxyyy'}])
|
20
|
+
documents = Signatory::Document.all
|
21
|
+
documents.count.should == 1
|
22
|
+
document = documents.first
|
23
|
+
document.subject.should == 'This is a test'
|
24
|
+
document.id.should == 'xxxyyy'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".find by id" do
|
29
|
+
it "returns the document with the specified id" do
|
30
|
+
stub_document('xxxyyy', :subject => 'Test number 2')
|
31
|
+
doc = Signatory::Document.find('xxxyyy')
|
32
|
+
doc.subject.should == 'Test number 2'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
<document>
|
2
|
+
<completed-at>2009-11-01T13:14:28-08:00</completed-at>
|
3
|
+
<thumbnail-url>https://thumbnail.png</thumbnail-url>
|
4
|
+
<message>Please sign the document.</message>
|
5
|
+
<form-fields>
|
6
|
+
<form-field>
|
7
|
+
<value>asdf</value>
|
8
|
+
<page>2</page>
|
9
|
+
<role-id>signer_B</role-id>
|
10
|
+
<name>Component 1</name>
|
11
|
+
<id>a_92208_asdf1234asdf_4709</id>
|
12
|
+
</form-field>
|
13
|
+
</form-fields>
|
14
|
+
<state>signed</state>
|
15
|
+
<pdf-url>https://pdfurl.pdf</pdf-url>
|
16
|
+
<deleted-at nil="true"></deleted-at>
|
17
|
+
<created-at>2009-11-01T12:29:36-08:00</created-at>
|
18
|
+
<is-public>false</is-public>
|
19
|
+
<signed-pdf-url>https://signedpdf.pdf</signed-pdf-url>
|
20
|
+
<original-filename>Application.pdf</original-filename>
|
21
|
+
<size>231740</size>
|
22
|
+
<recipients>
|
23
|
+
<recipient>
|
24
|
+
<state>signed</state>
|
25
|
+
<role-id>signer_B</role-id>
|
26
|
+
<must-sign>true</must-sign>
|
27
|
+
<is-sender>false</is-sender>
|
28
|
+
<email>support@rightsignature.com</email>
|
29
|
+
<name>John Bellingham</name>
|
30
|
+
</recipient>
|
31
|
+
</recipients>
|
32
|
+
<pages>
|
33
|
+
<page>
|
34
|
+
<original-template-filename>disclosure.pdf</original-template-filename>
|
35
|
+
<page-number>1</page-number>
|
36
|
+
<original-template-guid>a_154_fqLTIcNgcuIejFdhkVra</original-template-guid>
|
37
|
+
</page>
|
38
|
+
<page>
|
39
|
+
<original-template-filename>Application.pdf</original-template-filename>
|
40
|
+
<page-number>2</page-number>
|
41
|
+
<original-template-guid>a_311_yDhSZmJDtNEdPoZjfeF</original-template-guid>
|
42
|
+
</page>
|
43
|
+
</pages>
|
44
|
+
<subject><%= options[:subject] || "Employment Application" %></subject>
|
45
|
+
<guid><%= options[:guid] || 'ABCXYZ' %></guid>
|
46
|
+
<callback-location nil="true"></callback-location>
|
47
|
+
<processing-state>done-processing</processing-state>
|
48
|
+
<original-url>https://originaldoc.doc</original-url>
|
49
|
+
<content-type>package</content-type>
|
50
|
+
<expires-on>2009-11-06T16:00:00-08:00</expires-on>
|
51
|
+
</document>
|