autentique 0.1.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 +7 -0
- data/CHANGELOG.md +62 -0
- data/CONTRIBUTING.md +254 -0
- data/LICENSE +21 -0
- data/README.md +504 -0
- data/autentique.gemspec +33 -0
- data/lib/autentique/client.rb +101 -0
- data/lib/autentique/errors.rb +31 -0
- data/lib/autentique/models/document.rb +43 -0
- data/lib/autentique/models/document_input.rb +43 -0
- data/lib/autentique/models/signature.rb +41 -0
- data/lib/autentique/models/signer_input.rb +29 -0
- data/lib/autentique/resources/documents/create.rb +33 -0
- data/lib/autentique/resources/documents/delete.rb +26 -0
- data/lib/autentique/resources/documents/find.rb +45 -0
- data/lib/autentique/resources/documents/list.rb +41 -0
- data/lib/autentique/resources/documents/pending.rb +40 -0
- data/lib/autentique/resources/documents.rb +164 -0
- data/lib/autentique/resources/folders.rb +78 -0
- data/lib/autentique/resources.rb +6 -0
- data/lib/autentique/version.rb +5 -0
- data/lib/autentique.rb +74 -0
- metadata +98 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Models
|
|
5
|
+
class DocumentInput
|
|
6
|
+
attr_accessor :name, :message, :reminder, :sortable, :footer, :refusable,
|
|
7
|
+
:qualified, :scrolling_required, :stop_on_rejected,
|
|
8
|
+
:new_signature_style, :show_audit_page, :ignore_cpf,
|
|
9
|
+
:ignore_birthdate, :email_template_id, :deadline_at,
|
|
10
|
+
:cc, :expiration, :configs, :locale
|
|
11
|
+
|
|
12
|
+
def initialize(attributes = {})
|
|
13
|
+
attributes.each do |key, value|
|
|
14
|
+
send("#{key}=", value) if respond_to?("#{key}=")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_h
|
|
19
|
+
{
|
|
20
|
+
name: name,
|
|
21
|
+
message: message,
|
|
22
|
+
reminder: reminder,
|
|
23
|
+
sortable: sortable,
|
|
24
|
+
footer: footer,
|
|
25
|
+
refusable: refusable,
|
|
26
|
+
qualified: qualified,
|
|
27
|
+
scrolling_required: scrolling_required,
|
|
28
|
+
stop_on_rejected: stop_on_rejected,
|
|
29
|
+
new_signature_style: new_signature_style,
|
|
30
|
+
show_audit_page: show_audit_page,
|
|
31
|
+
ignore_cpf: ignore_cpf,
|
|
32
|
+
ignore_birthdate: ignore_birthdate,
|
|
33
|
+
email_template_id: email_template_id,
|
|
34
|
+
deadline_at: deadline_at,
|
|
35
|
+
cc: cc,
|
|
36
|
+
expiration: expiration,
|
|
37
|
+
configs: configs,
|
|
38
|
+
locale: locale
|
|
39
|
+
}.compact
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Models
|
|
5
|
+
class Signature
|
|
6
|
+
attr_reader :public_id, :name, :email, :created_at, :action, :link,
|
|
7
|
+
:user, :viewed, :signed, :rejected, :email_events, :delivery_method
|
|
8
|
+
|
|
9
|
+
def initialize(attributes = {})
|
|
10
|
+
@public_id = attributes['public_id']
|
|
11
|
+
@name = attributes['name']
|
|
12
|
+
@email = attributes['email']
|
|
13
|
+
@created_at = attributes['created_at']
|
|
14
|
+
@action = attributes['action']
|
|
15
|
+
@link = attributes['link']
|
|
16
|
+
@user = attributes['user']
|
|
17
|
+
@viewed = attributes['viewed']
|
|
18
|
+
@signed = attributes['signed']
|
|
19
|
+
@rejected = attributes['rejected']
|
|
20
|
+
@email_events = attributes['email_events']
|
|
21
|
+
@delivery_method = attributes['delivery_method']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def signed?
|
|
25
|
+
!@signed.nil?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def rejected?
|
|
29
|
+
!@rejected.nil?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def pending?
|
|
33
|
+
@signed.nil? && @rejected.nil?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def short_link
|
|
37
|
+
@link&.dig('short_link')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Models
|
|
5
|
+
class SignerInput
|
|
6
|
+
attr_accessor :email, :phone, :name, :action, :delivery_method,
|
|
7
|
+
:configs, :security_verifications, :positions
|
|
8
|
+
|
|
9
|
+
def initialize(attributes = {})
|
|
10
|
+
attributes.each do |key, value|
|
|
11
|
+
send("#{key}=", value) if respond_to?("#{key}=")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
{
|
|
17
|
+
email: email,
|
|
18
|
+
phone: phone,
|
|
19
|
+
name: name,
|
|
20
|
+
action: action,
|
|
21
|
+
delivery_method: delivery_method,
|
|
22
|
+
configs: configs,
|
|
23
|
+
security_verifications: security_verifications,
|
|
24
|
+
positions: positions
|
|
25
|
+
}.compact
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Resources
|
|
5
|
+
class Documents
|
|
6
|
+
module Create
|
|
7
|
+
def create(file:, document:, signers:, organization_id: nil, folder_id: nil, sandbox: nil) # rubocop:disable Metrics/ParameterLists
|
|
8
|
+
doc_input = document.is_a?(Models::DocumentInput) ? document : Models::DocumentInput.new(document)
|
|
9
|
+
signer_inputs = signers.map { |s| s.is_a?(Models::SignerInput) ? s : Models::SignerInput.new(s) }
|
|
10
|
+
|
|
11
|
+
use_sandbox = sandbox.nil? ? client.sandbox : sandbox
|
|
12
|
+
if use_sandbox
|
|
13
|
+
doc_hash = doc_input.to_h.merge(sandbox: true)
|
|
14
|
+
doc_input = Models::DocumentInput.new(doc_hash)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
response = upload_document(
|
|
18
|
+
file: file,
|
|
19
|
+
document: doc_input,
|
|
20
|
+
signers: signer_inputs,
|
|
21
|
+
organization_id: organization_id,
|
|
22
|
+
folder_id: folder_id
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
document_data = response.dig('data', 'createDocument')
|
|
26
|
+
raise QueryError.new('Failed to create document', response['errors']) if document_data.nil?
|
|
27
|
+
|
|
28
|
+
Models::Document.new(document_data)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Resources
|
|
5
|
+
class Documents
|
|
6
|
+
module Delete
|
|
7
|
+
# Delete a document
|
|
8
|
+
#
|
|
9
|
+
# @param id [String] The document ID (UUID)
|
|
10
|
+
# @return [Boolean]
|
|
11
|
+
def delete(id)
|
|
12
|
+
query = client.graphql_client.parse <<-GRAPHQL
|
|
13
|
+
mutation($id: UUID!) {
|
|
14
|
+
deleteDocument(id: $id)
|
|
15
|
+
}
|
|
16
|
+
GRAPHQL
|
|
17
|
+
|
|
18
|
+
result = client.query(query, variables: { id: id })
|
|
19
|
+
raise QueryError.new('Query failed', result.errors.messages) if result.errors.any?
|
|
20
|
+
|
|
21
|
+
result.data.delete_document
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Resources
|
|
5
|
+
class Documents
|
|
6
|
+
module Find
|
|
7
|
+
def find(id) # rubocop:disable Metrics/MethodLength
|
|
8
|
+
query = client.graphql_client.parse <<-GRAPHQL
|
|
9
|
+
query($id: UUID!) {
|
|
10
|
+
document(id: $id) {
|
|
11
|
+
id
|
|
12
|
+
name
|
|
13
|
+
refusable
|
|
14
|
+
sortable
|
|
15
|
+
created_at
|
|
16
|
+
files { original signed }
|
|
17
|
+
signatures {
|
|
18
|
+
public_id
|
|
19
|
+
name
|
|
20
|
+
email
|
|
21
|
+
created_at
|
|
22
|
+
action { name }
|
|
23
|
+
link { short_link }
|
|
24
|
+
user { id name email }
|
|
25
|
+
viewed { created_at }
|
|
26
|
+
signed { created_at }
|
|
27
|
+
rejected { created_at reason }
|
|
28
|
+
email_events { sent opened delivered refused reason }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
GRAPHQL
|
|
33
|
+
|
|
34
|
+
result = client.query(query, variables: { id: id })
|
|
35
|
+
raise QueryError.new('Query failed', result.errors.messages) if result.errors.any?
|
|
36
|
+
|
|
37
|
+
document_data = result.data.document
|
|
38
|
+
raise NotFoundError, "Document with ID #{id} not found" if document_data.nil?
|
|
39
|
+
|
|
40
|
+
Models::Document.new(document_data.to_h)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Resources
|
|
5
|
+
class Documents
|
|
6
|
+
module List
|
|
7
|
+
def list(status: nil, limit: 60, page: 1) # rubocop:disable Metrics/MethodLength
|
|
8
|
+
query_string = if status
|
|
9
|
+
<<-GRAPHQL
|
|
10
|
+
query($status: DocumentStatusEnum, $limit: Int!, $page: Int!) {
|
|
11
|
+
documents(status: $status, limit: $limit, page: $page) {
|
|
12
|
+
total
|
|
13
|
+
data { id name created_at signatures { public_id name email } }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
GRAPHQL
|
|
17
|
+
else
|
|
18
|
+
<<-GRAPHQL
|
|
19
|
+
query($limit: Int, $page: Int) {
|
|
20
|
+
documents(limit: $limit, page: $page) {
|
|
21
|
+
total
|
|
22
|
+
data { id name created_at signatures { public_id name email } }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
GRAPHQL
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
query = client.graphql_client.parse(query_string)
|
|
29
|
+
variables = { limit: limit, page: page }
|
|
30
|
+
variables[:status] = status if status
|
|
31
|
+
|
|
32
|
+
result = client.query(query, variables: variables)
|
|
33
|
+
raise QueryError.new('Query failed', result.errors.messages) if result.errors.any?
|
|
34
|
+
|
|
35
|
+
docs = result.data.documents&.data || []
|
|
36
|
+
docs.map { |doc| Models::Document.new(doc.to_h) }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Resources
|
|
5
|
+
class Documents
|
|
6
|
+
module Pending
|
|
7
|
+
def self.pending_query(client)
|
|
8
|
+
client.graphql_client.parse <<~GRAPHQL
|
|
9
|
+
query($limit: Int!, $page: Int!) {
|
|
10
|
+
documents(status: PENDING, limit: $limit, page: $page) {
|
|
11
|
+
total
|
|
12
|
+
data {
|
|
13
|
+
id
|
|
14
|
+
name
|
|
15
|
+
created_at
|
|
16
|
+
signatures {
|
|
17
|
+
public_id
|
|
18
|
+
name
|
|
19
|
+
email
|
|
20
|
+
user { id name email phone }
|
|
21
|
+
delivery_method
|
|
22
|
+
email_events { sent opened delivered refused reason }
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
GRAPHQL
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def pending(limit: 60, page: 1)
|
|
31
|
+
query = Pending.pending_query(client)
|
|
32
|
+
result = client.query(query, variables: { limit: limit, page: page })
|
|
33
|
+
raise QueryError.new('Query failed', result.errors.messages) if result.errors.any?
|
|
34
|
+
|
|
35
|
+
result.data.documents&.data&.map { |doc| Models::Document.new(doc.to_h) } || []
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'mime/types'
|
|
6
|
+
|
|
7
|
+
require_relative 'documents/create'
|
|
8
|
+
require_relative 'documents/find'
|
|
9
|
+
require_relative 'documents/pending'
|
|
10
|
+
require_relative 'documents/list'
|
|
11
|
+
require_relative 'documents/delete'
|
|
12
|
+
|
|
13
|
+
module Autentique
|
|
14
|
+
module Resources
|
|
15
|
+
class Documents
|
|
16
|
+
include Documents::Create
|
|
17
|
+
include Documents::Find
|
|
18
|
+
include Documents::Pending
|
|
19
|
+
include Documents::List
|
|
20
|
+
include Documents::Delete
|
|
21
|
+
|
|
22
|
+
attr_reader :client
|
|
23
|
+
|
|
24
|
+
def initialize(client)
|
|
25
|
+
@client = client
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Upload document using multipart/form-data
|
|
31
|
+
def upload_document(file:, document:, signers:, organization_id: nil, folder_id: nil)
|
|
32
|
+
uri = URI(Client::API_ENDPOINT)
|
|
33
|
+
|
|
34
|
+
# Build GraphQL mutation
|
|
35
|
+
mutation = build_create_mutation(organization_id, folder_id)
|
|
36
|
+
|
|
37
|
+
# Build variables
|
|
38
|
+
variables = {
|
|
39
|
+
document: document.to_h,
|
|
40
|
+
signers: signers.map(&:to_h),
|
|
41
|
+
file: nil
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Prepare multipart request
|
|
45
|
+
boundary = "----RubyAutentiqueGem#{Time.now.to_i}"
|
|
46
|
+
body = build_multipart_body(
|
|
47
|
+
mutation: mutation,
|
|
48
|
+
variables: variables,
|
|
49
|
+
file: file,
|
|
50
|
+
boundary: boundary
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Make request
|
|
54
|
+
http = build_http_client(uri)
|
|
55
|
+
request = Net::HTTP::Post.new(uri.path)
|
|
56
|
+
request['Authorization'] = "Bearer #{client.api_key}"
|
|
57
|
+
request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
|
|
58
|
+
request.body = body
|
|
59
|
+
|
|
60
|
+
response = http.request(request)
|
|
61
|
+
|
|
62
|
+
raise UploadError, "Upload failed: #{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess)
|
|
63
|
+
|
|
64
|
+
JSON.parse(response.body)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Build the GraphQL mutation string for document creation
|
|
68
|
+
def build_create_mutation(organization_id, folder_id) # rubocop:disable Metrics/MethodLength
|
|
69
|
+
mutation = <<-GRAPHQL
|
|
70
|
+
mutation CreateDocumentMutation(
|
|
71
|
+
$document: DocumentInput!,
|
|
72
|
+
$signers: [SignerInput!]!,
|
|
73
|
+
$file: Upload!
|
|
74
|
+
) {
|
|
75
|
+
createDocument(
|
|
76
|
+
document: $document,
|
|
77
|
+
signers: $signers,
|
|
78
|
+
file: $file
|
|
79
|
+
GRAPHQL
|
|
80
|
+
|
|
81
|
+
mutation += ",\n organization_id: #{organization_id}" if organization_id
|
|
82
|
+
mutation += ",\n folder_id: \"#{folder_id}\"" if folder_id
|
|
83
|
+
|
|
84
|
+
mutation += <<-GRAPHQL
|
|
85
|
+
) {
|
|
86
|
+
id
|
|
87
|
+
name
|
|
88
|
+
refusable
|
|
89
|
+
sortable
|
|
90
|
+
created_at
|
|
91
|
+
signatures {
|
|
92
|
+
public_id
|
|
93
|
+
name
|
|
94
|
+
email
|
|
95
|
+
created_at
|
|
96
|
+
action { name }
|
|
97
|
+
link { short_link }
|
|
98
|
+
user { id name email }
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
GRAPHQL
|
|
103
|
+
|
|
104
|
+
mutation
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Build multipart/form-data body for file uploads
|
|
108
|
+
def build_multipart_body(mutation:, variables:, file:, boundary:)
|
|
109
|
+
parts = []
|
|
110
|
+
parts.concat(build_operations_part(mutation, variables, boundary))
|
|
111
|
+
parts.concat(build_map_part(boundary))
|
|
112
|
+
parts.concat(build_file_part(file, boundary))
|
|
113
|
+
parts << "--#{boundary}--\r\n"
|
|
114
|
+
parts.join
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def build_operations_part(mutation, variables, boundary)
|
|
118
|
+
operations = { query: mutation, variables: variables }
|
|
119
|
+
[
|
|
120
|
+
"--#{boundary}\r\n",
|
|
121
|
+
"Content-Disposition: form-data; name=\"operations\"\r\n\r\n",
|
|
122
|
+
"#{operations.to_json}\r\n"
|
|
123
|
+
]
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def build_map_part(boundary)
|
|
127
|
+
map = { file: ['variables.file'] }
|
|
128
|
+
[
|
|
129
|
+
"--#{boundary}\r\n",
|
|
130
|
+
"Content-Disposition: form-data; name=\"map\"\r\n\r\n",
|
|
131
|
+
"#{map.to_json}\r\n"
|
|
132
|
+
]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def build_file_part(file, boundary)
|
|
136
|
+
content, name, type = extract_file_info(file)
|
|
137
|
+
[
|
|
138
|
+
"--#{boundary}\r\n",
|
|
139
|
+
"Content-Disposition: form-data; name=\"file\"; filename=\"#{name}\"\r\n",
|
|
140
|
+
"Content-Type: #{type}\r\n\r\n",
|
|
141
|
+
content,
|
|
142
|
+
"\r\n"
|
|
143
|
+
]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def extract_file_info(file)
|
|
147
|
+
if file.is_a?(String)
|
|
148
|
+
[File.binread(file), File.basename(file),
|
|
149
|
+
MIME::Types.type_for(file).first&.content_type || 'application/pdf']
|
|
150
|
+
elsif file.is_a?(Hash)
|
|
151
|
+
[file[:io].read, file[:name] || 'document.pdf', file[:mime_type] || 'application/pdf']
|
|
152
|
+
else
|
|
153
|
+
[file.read, 'document.pdf', 'application/pdf']
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def build_http_client(uri)
|
|
158
|
+
Net::HTTP.new(uri.host, uri.port).tap do |http|
|
|
159
|
+
http.use_ssl = true
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Autentique
|
|
4
|
+
module Resources
|
|
5
|
+
class Folders
|
|
6
|
+
attr_reader :client
|
|
7
|
+
|
|
8
|
+
def initialize(client)
|
|
9
|
+
@client = client
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# List all folders
|
|
13
|
+
#
|
|
14
|
+
# @return [Array<Hash>]
|
|
15
|
+
def list(limit: 30, page: 1)
|
|
16
|
+
query = client.graphql_client.parse <<-GRAPHQL
|
|
17
|
+
query($limit: Int!, $page: Int!) {
|
|
18
|
+
folders(limit: $limit, page: $page) {
|
|
19
|
+
total
|
|
20
|
+
data {
|
|
21
|
+
id
|
|
22
|
+
name
|
|
23
|
+
created_at
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
GRAPHQL
|
|
28
|
+
|
|
29
|
+
result = client.query(query, variables: { limit: limit, page: page })
|
|
30
|
+
raise QueryError.new('Query failed', result.errors.messages) if result.errors.any?
|
|
31
|
+
|
|
32
|
+
result.data.folders.data.map(&:to_h)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Create a new folder
|
|
36
|
+
#
|
|
37
|
+
# @param name [String] The folder name
|
|
38
|
+
# @param parent_id [String, nil] The parent folder ID
|
|
39
|
+
# @return [Hash]
|
|
40
|
+
def create(name:, parent_id: nil)
|
|
41
|
+
query = client.graphql_client.parse <<-GRAPHQL
|
|
42
|
+
mutation($folder: FolderInput!, $parent_id: UUID) {
|
|
43
|
+
createFolder(folder: $folder, parent_id: $parent_id) {
|
|
44
|
+
id
|
|
45
|
+
name
|
|
46
|
+
created_at
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
GRAPHQL
|
|
50
|
+
|
|
51
|
+
variables = { folder: { name: name } }
|
|
52
|
+
variables[:parent_id] = parent_id if parent_id
|
|
53
|
+
|
|
54
|
+
result = client.query(query, variables: variables)
|
|
55
|
+
raise QueryError.new('Query failed', result.errors.messages) if result.errors.any?
|
|
56
|
+
|
|
57
|
+
result.data.create_folder.to_h
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Delete a folder
|
|
61
|
+
#
|
|
62
|
+
# @param id [String] The folder ID
|
|
63
|
+
# @return [Boolean]
|
|
64
|
+
def delete(id:)
|
|
65
|
+
query = client.graphql_client.parse <<-GRAPHQL
|
|
66
|
+
mutation($id: UUID!) {
|
|
67
|
+
deleteFolder(id: $id)
|
|
68
|
+
}
|
|
69
|
+
GRAPHQL
|
|
70
|
+
|
|
71
|
+
result = client.query(query, variables: { id: id })
|
|
72
|
+
raise QueryError.new('Query failed', result.errors.messages) if result.errors.any?
|
|
73
|
+
|
|
74
|
+
result.data.delete_folder
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
data/lib/autentique.rb
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'autentique/version'
|
|
4
|
+
require_relative 'autentique/errors'
|
|
5
|
+
require_relative 'autentique/client'
|
|
6
|
+
require_relative 'autentique/models/document'
|
|
7
|
+
require_relative 'autentique/resources'
|
|
8
|
+
require_relative 'autentique/resources/documents'
|
|
9
|
+
require_relative 'autentique/resources/folders'
|
|
10
|
+
|
|
11
|
+
# Main module for the Autentique gem
|
|
12
|
+
#
|
|
13
|
+
# @example Basic usage
|
|
14
|
+
# client = Autentique::Client.new(api_key: 'your_api_key')
|
|
15
|
+
#
|
|
16
|
+
# # Create a document
|
|
17
|
+
# document = client.documents.create(
|
|
18
|
+
# file: '/path/to/contract.pdf',
|
|
19
|
+
# document: { name: 'Contract' },
|
|
20
|
+
# signers: [
|
|
21
|
+
# { email: 'signer@example.com', action: 'SIGN' }
|
|
22
|
+
# ]
|
|
23
|
+
# )
|
|
24
|
+
#
|
|
25
|
+
# # Retrieve a document
|
|
26
|
+
# doc = client.documents.find('document-uuid')
|
|
27
|
+
#
|
|
28
|
+
# # List pending documents
|
|
29
|
+
# pending_docs = client.documents.pending
|
|
30
|
+
#
|
|
31
|
+
module Autentique
|
|
32
|
+
class << self
|
|
33
|
+
# Configure the Autentique client with default settings
|
|
34
|
+
#
|
|
35
|
+
# @yield [Configuration] configuration object
|
|
36
|
+
# @return [Configuration]
|
|
37
|
+
def configure
|
|
38
|
+
yield configuration
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Get the current configuration
|
|
42
|
+
#
|
|
43
|
+
# @return [Configuration]
|
|
44
|
+
def configuration
|
|
45
|
+
@configuration ||= Configuration.new
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Create a new client with default configuration
|
|
49
|
+
#
|
|
50
|
+
# @return [Client]
|
|
51
|
+
def client
|
|
52
|
+
@client ||= Client.new(
|
|
53
|
+
api_key: configuration.api_key,
|
|
54
|
+
sandbox: configuration.sandbox
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Reset the configuration
|
|
59
|
+
def reset
|
|
60
|
+
@configuration = Configuration.new
|
|
61
|
+
@client = nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Configuration class for global settings
|
|
66
|
+
class Configuration
|
|
67
|
+
attr_accessor :api_key, :sandbox
|
|
68
|
+
|
|
69
|
+
def initialize
|
|
70
|
+
@api_key = ENV.fetch('AUTENTIQUE_API_KEY', nil)
|
|
71
|
+
@sandbox = false
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|