class Crm::Core::AttachmentStore

AttachmentStore represents an attachment of an {Activity::Comment activity comment}.

To upload a file as an attachment, add it to comment_attachments. The SDK will automatically upload the content of the file.

Note that this method of uploading an attachment using a browser will upload the file twice. It is first uploaded to the ruby application (e.g. Rails) which then uploads it to AWS S3.

To upload the attachment directly to AWS S3 (i.e. bypassing the ruby application), please proceed as follows:

  1. Request an upload permission ({Crm::Core::AttachmentStore.generate_upload_permission AttachmentStore.generate_upload_permission}). The response grants the client permission to upload a file to a given key on AWS S3. This permission is valid for one hour.

  2. Upload the file to the URL (permission.url or permission.uri), together with the fields (permission.fields) as parameters. AWS S3 itself then verifies the signature of these parameters prior to accepting the upload.

  3. Attach the upload to a new activity comment by setting its comment_attachments attribute to an array of upload IDs. The client may append filenames to the upload IDs for producing download URLs with proper filenames later on.

    The format of comment_attachments is ["upload_id/filename.ext", ...], e.g. ["e13f0d960feeb2b2903bd/screenshot.jpg"]. JustRelate WebCRM in turn translates these upload IDs to attachment IDs. Syntactically they look the same. Upload IDs, however, are only temporary, whereas attachment IDs are permanent. If the client appended a filename to the upload ID, the attachment ID will contain this filename, too. Otherwise, the attachment ID ends with "/file". Please note that JustRelate WebCRM replaces filename characters other than a-zA-Z0-9.+- with a dash. Multiple dashes will be joined into a single dash.

  4. Later, when downloading the attachment, pass the attachment ID to {Crm::Core::AttachmentStore.generate_download_url}. JustRelate WebCRM returns a signed AWS S3 URL that remains valid for 5 minutes.

@api public

Public Class Methods

generate_download_url(attachment_id) click to toggle source

Generates a download URL for the given attachment. The URL is valid for a couple of minutes. Hence, it is recommended to have such URLs generated on demand. @param attachment_id [String] the ID of an attachment. @return [String] @api public

# File lib/crm/core/attachment_store.rb, line 88
def generate_download_url(attachment_id)
  response = Core::RestApi.instance.post("attachment_store/generate_download_url",
      {'attachment_id' => attachment_id})
  resolve_uri(response["url"]).to_s
end
generate_upload_permission() click to toggle source

Obtains the permission to upload a file manually. The permission is valid for a couple of minutes. Hence, it is recommended to have such permissions generated on demand. @return [Permission] @api public

# File lib/crm/core/attachment_store.rb, line 76
def generate_upload_permission
  perm = Core::RestApi.instance.post("attachment_store/generate_upload_permission", {})
  uri = resolve_uri(perm["url"])
  Permission.new(uri, uri.to_s, perm["fields"], perm["upload_id"])
end
upload(file) click to toggle source

Uploads a file to S3. @param file [File] the file to be uploaded. @return [String] the upload ID. Add this ID to the comment_attachments attribute

of an activity.
# File lib/crm/core/attachment_store.rb, line 98
def upload(file)
  permission = generate_upload_permission

  file_name = File.basename(file.path)
  upload_io = UploadIO.new(file, 'application/octet-stream', file_name)
  params = permission.fields.merge(file: upload_io)
  request = Net::HTTP::Post::Multipart.new(permission.uri, params)

  response = Core::ConnectionManager.new(permission.uri).request(request)

  if response.code.starts_with?('2')
    [permission.upload_id, file_name].compact.join('/')
  else
    raise Errors::ServerError, "File upload failed with code #{response.code}"
  end
end

Private Class Methods

resolve_uri(url) click to toggle source
# File lib/crm/core/attachment_store.rb, line 117
def resolve_uri(url)
  Core::RestApi.instance.resolve_uri(url)
end