Skip to content

Commit d0536b0

Browse files
add code example
1 parent 4e72270 commit d0536b0

File tree

8 files changed

+613
-481
lines changed

8 files changed

+613
-481
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ group :test do
6868
gem 'test-unit'
6969
end
7070

71-
gem 'docusign_admin', '~> 1.3.0'
71+
gem 'docusign_admin', '~> 2.0.0.rc1'
7272
gem 'docusign_click', '~> 1.4.0'
7373
gem 'docusign_esign', '~> 4.0.0.rc1'
7474
gem 'docusign_maestro', '~> 2.0.0.rc1'

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ GEM
111111
connection_pool (2.4.1)
112112
crass (1.0.6)
113113
date (3.3.4)
114-
docusign_admin (1.3.0)
114+
docusign_admin (2.0.0.rc1)
115115
addressable (~> 2.7, >= 2.7.0)
116116
json (~> 2.1, >= 2.1.0)
117117
jwt (~> 2.2, >= 2.2.1)
@@ -393,7 +393,7 @@ DEPENDENCIES
393393
capybara (~> 3.40.0)
394394
chromedriver-helper (~> 2.1.1)
395395
coffee-rails (~> 5.0.0)
396-
docusign_admin (~> 1.3.0)
396+
docusign_admin (~> 2.0.0.rc1)
397397
docusign_click (~> 1.4.0)
398398
docusign_esign (~> 4.0.0.rc1)
399399
docusign_maestro (~> 2.0.0.rc1)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
class AdminApi::Aeg013CreateAccountController < EgController
2+
before_action -> { check_auth('Admin') }
3+
before_action -> { @example = Utils::ManifestUtils.new.get_example(@manifest, 13, 'Admin') }
4+
5+
def create
6+
args = {
7+
access_token: session['ds_access_token'],
8+
organization_id: session['organization_id'],
9+
subscription_id: session['subscription_id'],
10+
plan_id: session['plan_id'],
11+
email: param_gsub(params['email']),
12+
first_name: param_gsub(params['first_name']),
13+
last_name: param_gsub(params['last_name'])
14+
}
15+
16+
results = AdminApi::Eg013CreateAccountService.new(args).worker
17+
18+
@title = @example['ExampleName']
19+
@message = @example['ResultsPageText']
20+
@json = results.to_json.to_json
21+
render 'ds_common/example_done'
22+
rescue DocuSign_Admin::ApiError => e
23+
handle_error(e)
24+
end
25+
26+
def get
27+
super
28+
session[:organization_id] = AdminApi::GetDataService.new(session).get_organization_id if session[:organization_id].nil?
29+
args = {
30+
access_token: session['ds_access_token'],
31+
organization_id: session['organization_id']
32+
}
33+
plan_items = AdminApi::Eg013CreateAccountService.new(args).get_organization_plan_items
34+
print plan_items
35+
session['subscription_id'] = plan_items[0].subscription_id
36+
session['plan_id'] = plan_items[0].plan_id
37+
end
38+
end
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
3+
class AdminApi::Eg013CreateAccountService
4+
attr_reader :args
5+
6+
def initialize(args)
7+
@args = args
8+
end
9+
10+
def worker
11+
#ds-snippet-start:Admin13Step2
12+
configuration = DocuSign_Admin::Configuration.new
13+
configuration.host = Rails.configuration.admin_host
14+
15+
api_client = DocuSign_Admin::ApiClient.new(configuration)
16+
api_client.set_default_header('Authorization', "Bearer #{args[:access_token]}")
17+
#ds-snippet-end:Admin13Step2
18+
19+
#ds-snippet-start:Admin13Step4
20+
source_account = DocuSign_Admin::AssetGroupAccountCloneSourceAccount.new
21+
source_account.id = args[:source_account_id]
22+
23+
target_account_admin = DocuSign_Admin::SubAccountCreateRequestSubAccountCreationTargetAccountAdmin.new
24+
target_account_admin.first_name = args[:first_name]
25+
target_account_admin.last_name = args[:last_name]
26+
target_account_admin.email = args[:email]
27+
target_account_admin.locale = 'en'
28+
29+
target_account = DocuSign_Admin::SubAccountCreateRequestSubAccountCreationTargetAccountDetails.new
30+
target_account.name = 'CreatedThroughAPI'
31+
target_account.admin = target_account_admin
32+
target_account.country_code = 'US'
33+
34+
subscription_details = DocuSign_Admin::SubAccountCreateRequestSubAccountCreationSubscription.new
35+
subscription_details.id = args[:subscription_id]
36+
subscription_details.plan_id = args[:plan_id]
37+
subscription_details.modules = []
38+
39+
account_data = DocuSign_Admin::SubAccountCreateRequest.new
40+
account_data.subscription_details = subscription_details
41+
account_data.target_account = target_account
42+
#ds-snippet-end:Admin13Step4
43+
44+
#ds-snippet-start:Admin13Step5
45+
asset_group_api = DocuSign_Admin::ProvisionAssetGroupApi.new(api_client)
46+
asset_group_api.create_asset_group_account(args[:organization_id], account_data)
47+
#ds-snippet-end:Admin13Step5
48+
end
49+
50+
def get_organization_plan_items
51+
configuration = DocuSign_Admin::Configuration.new
52+
configuration.host = Rails.configuration.admin_host
53+
54+
api_client = DocuSign_Admin::ApiClient.new(configuration)
55+
api_client.set_default_header('Authorization', "Bearer #{args[:access_token]}")
56+
57+
#ds-snippet-start:Admin13Step3
58+
asset_group_api = DocuSign_Admin::ProvisionAssetGroupApi.new(api_client)
59+
asset_group_api.get_organization_plan_items(args[:organization_id])
60+
#ds-snippet-end:Admin13Step3
61+
end
62+
end

app/services/jwt_auth/jwt_creator.rb

Lines changed: 134 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,134 @@
1-
require 'yaml'
2-
3-
module JwtAuth
4-
class JwtCreator
5-
include ApiCreator
6-
7-
attr_reader :session, :api_client, :state
8-
9-
# Docusign authorization URI to obtain individual consent
10-
# https://developers.docusign.com/platform/auth/jwt/jwt-get-token
11-
# https://developers.docusign.com/platform/auth/consent/obtaining-individual-consent/
12-
def self.consent_url(state, api)
13-
# GET /oauth/auth
14-
# This endpoint is used to obtain consent and is the first step in several authentication flows.
15-
# https://developers.docusign.com/platform/auth/reference/obtain-consent
16-
scope = 'signature impersonation' if %w[eSignature Monitor].include?(api)
17-
scope = 'signature impersonation dtr.rooms.read dtr.rooms.write dtr.documents.read dtr.documents.write dtr.profile.read dtr.profile.write dtr.company.read dtr.company.write room_forms' if api == 'Rooms'
18-
scope = 'signature impersonation click.manage click.send' if api == 'Click'
19-
scope = 'signature impersonation organization_read group_read permission_read user_read user_write account_read domain_read identity_provider_read user_data_redact asset_group_account_read asset_group_account_clone_write asset_group_account_clone_read' if api == 'Admin'
20-
scope = 'signature webforms_read webforms_instance_read webforms_instance_write' if api == 'WebForms'
21-
scope = 'signature aow_manage' if api == 'Maestro'
22-
23-
base_uri = "#{Rails.configuration.authorization_server}/oauth/auth"
24-
response_type = 'code'
25-
scopes = ERB::Util.url_encode(scope) # https://developers.docusign.com/platform/auth/reference/scopes/
26-
client_id = Rails.configuration.jwt_integration_key
27-
redirect_uri = "#{Rails.configuration.app_url}/auth/docusign/callback"
28-
consent_url = "#{base_uri}?response_type=#{response_type}&scope=#{scopes}&client_id=#{client_id}&state=#{state}&redirect_uri=#{redirect_uri}"
29-
Rails.logger.info "==> Obtain Consent Grant required: #{consent_url}"
30-
consent_url
31-
end
32-
33-
def initialize(session)
34-
@session = session
35-
scope = 'signature impersonation'
36-
@client_module = DocuSign_eSign
37-
if session[:api] == 'Rooms'
38-
scope = "#{scope} signature dtr.rooms.read dtr.rooms.write dtr.documents.read dtr.documents.write dtr.profile.read dtr.profile.write dtr.company.read dtr.company.write room_forms"
39-
@client_module = DocuSign_Rooms
40-
end
41-
if session[:api] == 'Click'
42-
scope = 'signature click.manage click.send'
43-
@client_module = DocuSign_Click
44-
end
45-
@client_module = DocuSign_Monitor if session[:api] == 'Monitor'
46-
if session[:api] == 'Admin'
47-
scope = 'signature organization_read group_read permission_read user_read user_write account_read domain_read identity_provider_read user_data_redact asset_group_account_read asset_group_account_clone_write asset_group_account_clone_read'
48-
@client_module = DocuSign_Admin
49-
end
50-
if session[:api] == 'WebForms'
51-
scope = 'signature webforms_read webforms_instance_read webforms_instance_write'
52-
@client_module = DocuSign_WebForms
53-
end
54-
55-
@scope = scope
56-
@api_client = create_initial_api_client(host: Rails.configuration.aud, client_module: @client_module, debugging: false)
57-
end
58-
59-
# @return [Boolean] `true` if the token was successfully updated, `false` if consent still needs to be grant'ed
60-
def check_jwt_token
61-
rsa_pk = docusign_rsa_private_key_file
62-
begin
63-
# docusign_esign: POST /oauth/token
64-
# This endpoint enables you to exchange an authorization code or JWT token for an access token.
65-
# https://developers.docusign.com/platform/auth/reference/obtain-access-token
66-
token = api_client.request_jwt_user_token(Rails.configuration.jwt_integration_key, Rails.configuration.impersonated_user_guid, rsa_pk, 3600, @scope)
67-
rescue OpenSSL::PKey::RSAError => e
68-
Rails.logger.error e.inspect
69-
raise "Please add your private RSA key to: #{rsa_pk}" if File.read(rsa_pk).starts_with? '{RSA_PRIVATE_KEY}'
70-
71-
raise
72-
rescue @client_module::ApiError => e
73-
Rails.logger.warn e.inspect
74-
75-
return false if e.response_body.nil?
76-
77-
body = JSON.parse(e.response_body)
78-
79-
if body['error'] == 'consent_required'
80-
false
81-
else
82-
details = <<~TXT
83-
See: https://support.docusign.com/articles/DocuSign-Developer-Support-FAQs#Troubleshoot-JWT-invalid_grant
84-
or https://developers.docusign.com/esign-rest-api/guides/authentication/oauth2-code-grant#troubleshooting-errors
85-
or try enabling `configuration.debugging = true` in the initialize method above for more logging output
86-
TXT
87-
raise "JWT response error: `#{body}`. #{details}"
88-
end
89-
else
90-
update_account_info(token)
91-
true
92-
end
93-
end
94-
95-
private
96-
97-
def update_account_info(token)
98-
# docusign_esign: GET /oauth/userinfo
99-
# This endpoint returns information on the caller, including their name, email, account, and organizational information.
100-
# The response includes the base_uri needed to interact with the Docusign APIs.
101-
# https://developers.docusign.com/platform/auth/reference/user-info
102-
user_info_response = api_client.get_user_info(token.access_token)
103-
accounts = user_info_response.accounts
104-
target_account_id = Rails.configuration.target_account_id
105-
account = get_account(accounts, target_account_id)
106-
store_data(token, user_info_response, account)
107-
108-
api_client.config.host = account.base_uri
109-
Rails.logger.info "==> JWT: Received token for impersonated user which will expire in: #{token.expires_in.to_i.seconds / 1.hour} hour at: #{Time.at(token.expires_in.to_i.seconds.from_now)}"
110-
end
111-
112-
def store_data(token, user_info, account)
113-
session[:ds_access_token] = token.access_token
114-
session[:ds_expires_at] = token.expires_in.to_i.seconds.from_now.to_i
115-
session[:ds_user_name] = user_info.name
116-
session[:ds_account_id] = account.account_id
117-
session[:ds_base_path] = account.base_uri
118-
session[:ds_account_name] = account.account_name
119-
end
120-
121-
def get_account(accounts, target_account_id)
122-
if target_account_id.present?
123-
return accounts.find { |acct| acct.account_id == target_account_id }
124-
raise "The user does not have access to account #{target_account_id}"
125-
else
126-
accounts.find(&:is_default)
127-
end
128-
end
129-
130-
def docusign_rsa_private_key_file
131-
File.join(Rails.root, 'config', 'docusign_private_key.txt')
132-
end
133-
end
134-
end
1+
require 'yaml'
2+
3+
module JwtAuth
4+
class JwtCreator
5+
include ApiCreator
6+
7+
attr_reader :session, :api_client, :state
8+
9+
# Docusign authorization URI to obtain individual consent
10+
# https://developers.docusign.com/platform/auth/jwt/jwt-get-token
11+
# https://developers.docusign.com/platform/auth/consent/obtaining-individual-consent/
12+
def self.consent_url(state, api)
13+
# GET /oauth/auth
14+
# This endpoint is used to obtain consent and is the first step in several authentication flows.
15+
# https://developers.docusign.com/platform/auth/reference/obtain-consent
16+
scope = 'signature impersonation' if %w[eSignature Monitor].include?(api)
17+
scope = 'signature impersonation dtr.rooms.read dtr.rooms.write dtr.documents.read dtr.documents.write dtr.profile.read dtr.profile.write dtr.company.read dtr.company.write room_forms' if api == 'Rooms'
18+
scope = 'signature impersonation click.manage click.send' if api == 'Click'
19+
scope = 'signature impersonation organization_read group_read permission_read user_read user_write account_read domain_read identity_provider_read user_data_redact asset_group_account_read asset_group_account_clone_write asset_group_account_clone_read organization_sub_account_write organization_sub_account_read' if api == 'Admin'
20+
scope = 'signature webforms_read webforms_instance_read webforms_instance_write' if api == 'WebForms'
21+
scope = 'signature aow_manage' if api == 'Maestro'
22+
23+
base_uri = "#{Rails.configuration.authorization_server}/oauth/auth"
24+
response_type = 'code'
25+
scopes = ERB::Util.url_encode(scope) # https://developers.docusign.com/platform/auth/reference/scopes/
26+
client_id = Rails.configuration.jwt_integration_key
27+
redirect_uri = "#{Rails.configuration.app_url}/auth/docusign/callback"
28+
consent_url = "#{base_uri}?response_type=#{response_type}&scope=#{scopes}&client_id=#{client_id}&state=#{state}&redirect_uri=#{redirect_uri}"
29+
Rails.logger.info "==> Obtain Consent Grant required: #{consent_url}"
30+
consent_url
31+
end
32+
33+
def initialize(session)
34+
@session = session
35+
scope = 'signature impersonation'
36+
@client_module = DocuSign_eSign
37+
if session[:api] == 'Rooms'
38+
scope = "#{scope} signature dtr.rooms.read dtr.rooms.write dtr.documents.read dtr.documents.write dtr.profile.read dtr.profile.write dtr.company.read dtr.company.write room_forms"
39+
@client_module = DocuSign_Rooms
40+
end
41+
if session[:api] == 'Click'
42+
scope = 'signature click.manage click.send'
43+
@client_module = DocuSign_Click
44+
end
45+
@client_module = DocuSign_Monitor if session[:api] == 'Monitor'
46+
if session[:api] == 'Admin'
47+
scope = 'signature organization_read group_read permission_read user_read user_write account_read domain_read identity_provider_read user_data_redact asset_group_account_read asset_group_account_clone_write asset_group_account_clone_read organization_sub_account_write organization_sub_account_read'
48+
@client_module = DocuSign_Admin
49+
end
50+
if session[:api] == 'WebForms'
51+
scope = 'signature webforms_read webforms_instance_read webforms_instance_write'
52+
@client_module = DocuSign_WebForms
53+
end
54+
55+
@scope = scope
56+
@api_client = create_initial_api_client(host: Rails.configuration.aud, client_module: @client_module, debugging: false)
57+
end
58+
59+
# @return [Boolean] `true` if the token was successfully updated, `false` if consent still needs to be grant'ed
60+
def check_jwt_token
61+
rsa_pk = docusign_rsa_private_key_file
62+
begin
63+
# docusign_esign: POST /oauth/token
64+
# This endpoint enables you to exchange an authorization code or JWT token for an access token.
65+
# https://developers.docusign.com/platform/auth/reference/obtain-access-token
66+
token = api_client.request_jwt_user_token(Rails.configuration.jwt_integration_key, Rails.configuration.impersonated_user_guid, rsa_pk, 3600, @scope)
67+
rescue OpenSSL::PKey::RSAError => e
68+
Rails.logger.error e.inspect
69+
raise "Please add your private RSA key to: #{rsa_pk}" if File.read(rsa_pk).starts_with? '{RSA_PRIVATE_KEY}'
70+
71+
raise
72+
rescue @client_module::ApiError => e
73+
Rails.logger.warn e.inspect
74+
75+
return false if e.response_body.nil?
76+
77+
body = JSON.parse(e.response_body)
78+
79+
if body['error'] == 'consent_required'
80+
false
81+
else
82+
details = <<~TXT
83+
See: https://support.docusign.com/articles/DocuSign-Developer-Support-FAQs#Troubleshoot-JWT-invalid_grant
84+
or https://developers.docusign.com/esign-rest-api/guides/authentication/oauth2-code-grant#troubleshooting-errors
85+
or try enabling `configuration.debugging = true` in the initialize method above for more logging output
86+
TXT
87+
raise "JWT response error: `#{body}`. #{details}"
88+
end
89+
else
90+
update_account_info(token)
91+
true
92+
end
93+
end
94+
95+
private
96+
97+
def update_account_info(token)
98+
# docusign_esign: GET /oauth/userinfo
99+
# This endpoint returns information on the caller, including their name, email, account, and organizational information.
100+
# The response includes the base_uri needed to interact with the Docusign APIs.
101+
# https://developers.docusign.com/platform/auth/reference/user-info
102+
user_info_response = api_client.get_user_info(token.access_token)
103+
accounts = user_info_response.accounts
104+
target_account_id = Rails.configuration.target_account_id
105+
account = get_account(accounts, target_account_id)
106+
store_data(token, user_info_response, account)
107+
108+
api_client.config.host = account.base_uri
109+
Rails.logger.info "==> JWT: Received token for impersonated user which will expire in: #{token.expires_in.to_i.seconds / 1.hour} hour at: #{Time.at(token.expires_in.to_i.seconds.from_now)}"
110+
end
111+
112+
def store_data(token, user_info, account)
113+
session[:ds_access_token] = token.access_token
114+
session[:ds_expires_at] = token.expires_in.to_i.seconds.from_now.to_i
115+
session[:ds_user_name] = user_info.name
116+
session[:ds_account_id] = account.account_id
117+
session[:ds_base_path] = account.base_uri
118+
session[:ds_account_name] = account.account_name
119+
end
120+
121+
def get_account(accounts, target_account_id)
122+
if target_account_id.present?
123+
return accounts.find { |acct| acct.account_id == target_account_id }
124+
raise "The user does not have access to account #{target_account_id}"
125+
else
126+
accounts.find(&:is_default)
127+
end
128+
end
129+
130+
def docusign_rsa_private_key_file
131+
File.join(Rails.root, 'config', 'docusign_private_key.txt')
132+
end
133+
end
134+
end

0 commit comments

Comments
 (0)