class AdobeDocApi::Client

Constants

API_ENDPOINT_URL
JWT_URL

Attributes

access_token[R]
client_id[R]
client_secret[R]
location_url[R]
org_id[R]
raw_response[R]
tech_account_id[R]

Public Class Methods

new(private_key: nil, client_id: nil, client_secret: nil, org_id: nil, tech_account_id: nil, access_token: nil) click to toggle source
# File lib/adobe_doc_api/client.rb, line 13
def initialize(private_key: nil, client_id: nil, client_secret: nil, org_id: nil, tech_account_id: nil, access_token: nil)
  # TODO Need to validate if any params are missing and return error
  @client_id = client_id || AdobeDocApi.configuration.client_id
  @client_secret = client_secret || AdobeDocApi.configuration.client_secret
  @org_id = org_id || AdobeDocApi.configuration.org_id
  @tech_account_id = tech_account_id || AdobeDocApi.configuration.tech_account_id
  @private_key_path = private_key || AdobeDocApi.configuration.private_key_path
  @location_url = nil
  @output_file_path = nil
  @raw_response = nil
  @access_token = access_token || get_access_token(@private_key_path)
end

Public Instance Methods

get_access_token(private_key) click to toggle source
# File lib/adobe_doc_api/client.rb, line 26
def get_access_token(private_key)
  jwt_payload = {
    "iss" => @org_id,
    "sub" => @tech_account_id,
    "https://ims-na1.adobelogin.com/s/ent_documentcloud_sdk" => true,
    "aud" => "https://ims-na1.adobelogin.com/c/#{@client_id}",
    "exp" => (Time.now.utc + 60).to_i
  }

  rsa_private = OpenSSL::PKey::RSA.new File.read(private_key)

  jwt_token = JWT.encode jwt_payload, rsa_private, "RS256"

  connection = Faraday.new do |conn|
    conn.response :json, content_type: "application/json"
  end
  response = connection.post JWT_URL do |req|
    req.params["client_id"] = @client_id
    req.params["client_secret"] = @client_secret
    req.params["jwt_token"] = jwt_token
  end

  return response.body["access_token"]
end
submit(json:, template:, output:) click to toggle source
# File lib/adobe_doc_api/client.rb, line 51
def submit(json:, template:, output:)
  @output = output
  output_format = /docx/.match?(File.extname(@output)) ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/pdf"

  content_request = {
    "cpf:engine": {
      "repo:assetId": "urn:aaid:cpf:Service-52d5db6097ed436ebb96f13a4c7bf8fb"
    },
    "cpf:inputs": {
      documentIn: {
        "dc:format": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        "cpf:location": "InputFile0"
      },
      params: {
        "cpf:inline": {
          outputFormat: File.extname(@output).delete("."),
          jsonDataForMerge: json
        }
      }
    },
    "cpf:outputs": {
      documentOut: {
        "dc:format": output_format.to_s,
        "cpf:location": "multipartLabel"
      }
    }
  }.to_json

  connection = Faraday.new API_ENDPOINT_URL do |conn|
    conn.request :authorization, "Bearer", @access_token
    conn.headers["x-api-key"] = @client_id
    conn.request :multipart
    conn.request :url_encoded
    conn.response :json, content_type: "application/json"
  end

  payload = {"contentAnalyzerRequests" => content_request}
  payload[:InputFile0] = Faraday::FilePart.new(template, "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
  res = connection.post("/ops/:create", payload)
  status_code = res.body["cpf:status"]["status"].to_i
  @location_url = res.headers["location"]
  raise Error.new(status_code: status_code, msg: res.body["cpf:status"]) unless status_code == 202
  poll_for_file(@location_url)
end

Private Instance Methods

poll_for_file(url) click to toggle source
# File lib/adobe_doc_api/client.rb, line 98
def poll_for_file(url)
  connection = Faraday.new do |conn|
    conn.request :authorization, "Bearer", @access_token
    conn.headers["x-api-key"] = @client_id
  end
  counter = 0
  loop do
    sleep(6)
    response = connection.get(url)
    counter += 1
    if response.body.include?('"cpf:status":{"completed":true,"type":"","status":200}')
      @raw_response = response
      return write_to_file(response.body)
    else
      status = JSON.parse(response.body)["cpf:status"]
      raise Error.new(status_code: status["status"], msg: status) if status["status"] != 202
    end
    break if counter > 10
  rescue => e
    # Raise other exceptions
    raise(e)
  end
end
write_to_file(response_body) click to toggle source
# File lib/adobe_doc_api/client.rb, line 122
def write_to_file(response_body)
  line_index = []
  lines = response_body.split("\r\n")
  lines.each_with_index do |line, i|
    next if line.include?("--Boundary_") || line.match?(/^Content-(Type|Disposition):/) || line.empty? || JSON.parse(line.force_encoding("UTF-8").to_s)
  rescue
    line_index << i
  end

  return true if File.open(@output, "wb") { |f| f.write lines.map.with_index { |l, i| lines.at(i) if line_index.include?(i) }.compact.join("\r\n")}
  false
end