+ All Categories
Home > Documents > Amazon Software License · Events, was to send myself an email on a change. Custom Lightning...

Amazon Software License · Events, was to send myself an email on a change. Custom Lightning...

Date post: 29-May-2020
Category:
Upload: others
View: 2 times
Download: 0 times
Share this document with a friend
14
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. // Licensed under the Amazon Software License // http://aws.amazon.com/asl/ Amazon Software License 1. Definitions “Licensor” means any person or entity that distributes its Work. “Software” means the original work of authorship made available under this License. “Work” means the Software and any additions to or derivative works of the Software that are made available under this License. The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the meaning as provided under U.S. copyright law; provided, however, that for the purposes of this License, derivative works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work. Works, including the Software, are “made available” under this License by including in or with the Work either (a) a copyright notice referencing the applicability of this License to the Work, or (b) a copy of this License. 2. License Grants 2.1 Copyright Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free, copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and distribute its Work and any resulting derivative works in any form. 2.2 Patent Grant. Subject to the terms and conditions of this License, each Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free patent license to make, have made, use, sell, offer for sale, import, and otherwise transfer its Work, in whole or in part. The foregoing license applies only to the patent claims licensable by Licensor that would be infringed by Licensor’s Work (or portion thereof) individually and excluding any combinations with any other materials or technology. 3. Limitations 3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under this License, (b) you include a complete copy of this License with your distribution, and (c) you retain without modification any copyright, patent, trademark, or attribution notices that are present in the Work. 3.2 Derivative Works. You may specify that additional or different terms apply to the use, reproduction, and distribution of your derivative works of the Work (“Your Terms”) only
Transcript
Page 1: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

Amazon Software License

1. Definitions

“Licensor” means any person or entity that distributes its Work.

“Software” means the original work of authorship made available under this License.

“Work” means the Software and any additions to or derivative works of the Software that are

made available under this License.

The terms “reproduce,” “reproduction,” “derivative works,” and “distribution” have the meaning

as provided under U.S. copyright law; provided, however, that for the purposes of this License,

derivative works shall not include works that remain separable from, or merely link (or bind by

name) to the interfaces of, the Work.

Works, including the Software, are “made available” under this License by including in or with

the Work either (a) a copyright notice referencing the applicability of this License to the Work,

or (b) a copy of this License.

2. License Grants

2.1 Copyright Grant. Subject to the terms and conditions of this License, each Licensor

grants to you a perpetual, worldwide, non-exclusive, royalty-free, copyright license to

reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and

distribute its Work and any resulting derivative works in any form.

2.2 Patent Grant. Subject to the terms and conditions of this License, each Licensor

grants to you a perpetual, worldwide, non-exclusive, royalty-free patent license to make,

have made, use, sell, offer for sale, import, and otherwise transfer its Work, in whole or in

part. The foregoing license applies only to the patent claims licensable by Licensor that

would be infringed by Licensor’s Work (or portion thereof) individually and excluding any

combinations with any other materials or technology.

3. Limitations

3.1 Redistribution. You may reproduce or distribute the Work only if (a) you do so under

this License, (b) you include a complete copy of this License with your distribution, and

(c) you retain without modification any copyright, patent, trademark, or attribution notices

that are present in the Work.

3.2 Derivative Works. You may specify that additional or different terms apply to the use,

reproduction, and distribution of your derivative works of the Work (“Your Terms”) only

Page 2: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

if (a) Your Terms provide that the use limitation in Section 3.3 applies to your derivative

works, and (b) you identify the specific derivative works that are subject to Your Terms.

Notwithstanding Your Terms, this License (including the redistribution requirements in

Section 3.1) will continue to apply to the Work itself.

3.3 Use Limitation. The Work and any derivative works thereof only may be used or

intended for use with the web services, computing platforms or applications provided by

Amazon.com, Inc. or its affiliates, including Amazon Web Services, Inc.

3.4 Patent Claims. If you bring or threaten to bring a patent claim against any Licensor

(including any claim, cross-claim or counterclaim in a lawsuit) to enforce any patents that

you allege are infringed by any Work, then your rights under this License from such

Licensor (including the grants in Sections 2.1 and 2.2) will terminate immediately.

3.5 Trademarks. This License does not grant any rights to use any Licensor’s or its

affiliates’ names, logos, or trademarks, except as necessary to reproduce the notices

described in this License.

3.6 Termination. If you violate any term of this License, then your rights under this

License (including the grants in Sections 2.1 and 2.2) will terminate immediately.

4. Disclaimer of Warranty.

THE WORK IS PROVIDED “AS IS” WITHOUT WARRANTIES OR CONDITIONS OF ANY

KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS

OF M ERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-

INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER

THIS LICENSE. SOME STATES’ CONSUMER LAWS DO NOT ALLOW EXCLUSION OF

AN IMPLIED WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO YOU.

5. Limitation of Liability.

EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO

LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR

OTHERWISE SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES,

INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL

DAMAGES ARISING OUT OF OR RELATED TO THIS LICENSE, THE USE OR

INABILITY TO USE THE WORK (INCLUDING BUT NOT LIMITED TO LOSS OF

GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR DATA, COMPUTER

FAILURE OR MALFUNCTION, OR ANY OTHER COMM ERCIAL DAMAGES OR

LOSSES), EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF

SUCH DAMAGES.

Effective Date – April 18, 2008 © 2008 Amazon.com, Inc. or its affiliates. All rights reserved

Page 3: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

Connected App

Directions for creating the Connected App are provided in the previous blog.https://aws.amazon.com/blogs/apn/connecting-aws-and-salesforce-enables-enterprises-to-do-more-with-customer-data/

Custom Fields

Custom Fields Required: Under Setup, Object Manager, Opportunity

In order to store the location of the archived attachment/file, we decided to use a custom field in the Opportunity object that we created as part of the demonstration. The fields are:

S3 Archival URL, S3_Archival_URL__c, URL(255) s3bucket, s3bucket__c, Text(255) s3filename, s3filename__c, Text(255) s3key, s3key__c, Text(255)

The S3 Archival URL is used as a flag to indicate that the Opportunity has an archived attachment. We use to determine whether or not to show the s3download lightning component. The s3bucket and s3key are used to populate that s3download lightning component.

This method was used to show the ability to archive a single file. If we were to extrapolate this out to multiple files per opportunity, we could have queried the Attachments table because we are mirroring what is in there in s3, store the metadata in a datastore like DynamoDB, or query s3 directly to see what is archived under that opportunity key.

Platform Events

Platform Events are leveraged for near real-time integration. You can create a Platform Events though Salesforce Setup under Integrations. When the Opportunity Record is saved on a create or update, a platform event is triggered. The platform called “OppCRUD” was created for this demonstration. It has one custom field called “OppId” of Text(255) Data Type. Make sure it is “Deployed”.

To fire the Platform Event, we use one of the PLATFORM TOOLS, under Process Automation, called Process Builder. The steps are:

1. Object: Opportunity, Start the process: when a record is created or edited

Page 4: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

2. Criteria: Name: att archived 3. Criteria for Executing Actions: Conditions are met 4. Set Conditions:

i. Field: [Opportunity].S3_Archival_URL__c ii. Operator: Is null

iii. Type: Boolean iv. Value: True

5. Conditions: All of the conditions are met (AND) 6. Immediate Actions: Create a Record 7. Action Name: Create Platform Event 8. Record Type: OppCRUD 9. Set Field Values:

i. Field: OppId ii. Type: Field Reference

iii. Value: [Opportunity].Id

Make sure to activate the Process. One way to test the Process independent of Platform Events, was to send myself an email on a change.

Custom Lightning Components

Here are the Lightning Components and their code: To create a Lightning Component, use the Developer Console. Note: Once components are created, you can add them to the Opportunity Record Page via the Lightning App Builder under Platform Tools | User Interface.

Filename: s3download.cmp What does it do? When you created a custom lightning component, there is a “component” file with the CMP filename extension. This is a component and it is called “s3download”. A “controller” for it is also created called s3downloadController.js as well as an apex class is created which is called s3downloadController. There are 2 actions to be aware of which are “doInit” and “handleClick”. The initialization function takes the provided view’s recordId which is the Opportunity ID and queries the Opportunity data for additional fields, specifically s3filename, s3url, s3bucket, and s3key. The s3filename is used to populate the lightning layout, while the other items are used in the handleClick function to open a window which does the download magic described with the Visual Force page called “s3download”

<aura:component controller="s3downloadController" implements="flexipage:availableForAllPageTypes,force:hasRecordId" access="global" > <aura:attribute name="setMeOnInit" type="String" default="default value" /> <aura:attribute name="opportunity" type="Opportunity"/> <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

Page 5: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

<aura:attribute name="record" type="Object" description="The record object to be displayed"/> <aura:attribute name="OpptyRecord" type="Object" description="A simplified view record object to be displayed"/> <aura:attribute name="recordError" type="String" description="An error message bound to force:recordData"/> <force:recordData aura:id="record" layoutType="FULL" recordId="{!v.recordId}" targetError="{!v.recordError}" targetRecord="{!v.record}" targetFields="{!v.OpptyRecord }" mode="VIEW"/> <aura:attribute name="response" type="Map"/> <aura:attribute name="s3url" type="String" default="{!v.opportunity.S3_Archival_URL__c}"/> <aura:attribute name="s3bucket" type="String" default="{!v.opportunity.s3bucket__c}"/> <aura:attribute name="s3key" type="String" default="{!v.opportunity.s3key__c}"/> <div class="slds-m-around--none"> <!--Header part--> <div class="slds-page-header" role="banner"> <div class="slds-media__body"> <p class="slds-page-header__title slds-truncate" title="S3 Storage">S3 Storage<br/><br/></p> <lightning:layout verticalAlign="center"> <lightning:layoutItem class="slds-p-left_x-small"> {!v.opportunity.s3filename__c} &nbsp;&nbsp; </lightning:layoutItem> <lightning:layoutItem flexibility="grow"> <lightning:button variant="brand" label="Download" onclick="{!c.handleClick}" /> </lightning:layoutItem> </lightning:layout> </div> </div> </div> </aura:component>

Filename: s3downloadController.js What does it do? This is the associated Controller code for the s3download.cmp. It binds the variables to the opportunity record that is selected on the same screen. It also has a “handleClick” function which is fired off when the Download button is selected on s3download.cmp

({ doInit: function(cmp) { // Set the attribute value. // You could also fire an event here instead. cmp.set("v.setMeOnInit", "controller init magic!");

Page 6: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

var action = cmp.get("c.getOpportunity"); action.setParams({ id: cmp.get("v.recordId") }); action.setCallback(this, function(response){ var state = response.getState(); if (state === "SUCCESS") { cmp.set("v.opportunity", response.getReturnValue()); } }); $A.enqueueAction(action); }, handleClick : function(component, event) { var s3bucket = component.get("v.s3bucket"); var s3key = component.get("v.s3key"); var myurl = "https://yourname-demo-dev-ed--c.na57.visual.force.com/apex/s3download?bucket=" + s3bucket + "&key=" + s3key; console.log(myurl); window.open(myurl, "_blank"); //, "toolbar=yes,top=500,left=500,width=400,height=400"); } })

Filename: s3downloadController.apxc What does it do? This is the s3downloadController apex class. When s3downloadController.js calls this apxc from the initialization (doInit) function and brings back the opportunity that we are currently concerned with along with various details as an “opportunity” object. This is used in the s3download.cmp file. This apex class is used to construct the opportunity object using a query function with the Id as the key.

public class s3downloadController { @AuraEnabled public static Opportunity getOpportunity(Id id) { Opportunity opportunity = [ SELECT Id, Account.Name, Name, CloseDate, Amount, Description, StageName, s3key__c, s3filename__c, s3bucket__c, S3_Archival_URL__c FROM Opportunity WHERE Id = :id ]; return opportunity; } }

Custom Visual Force Page

Visual Force Page: s3download What does it do? This s3download visual force page is a javascript page which is called when

Page 7: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

the “Download” button is selected from the Lightning Component. It can only be called from the lightning component and uses the security built into Salesforce. We used a read-only accessKeyId and secretAccessKey to download the file from the s3 bucket. It is possible to obfuscate the accessKey and Secret further within Salesforce, or a Cognito Identity could have been used. The secrets are used to create a Signed URL which is used to download the file.

NOTE: WE DO NOT RECOMMEND USING THIS APPROACH IN PRODUCTION even though this page cannot be accessed except to those that have access to the Opportunity. We recommend leveraging the session token from your browser to authenticate/authorize.

<apex:page > <script src="https://sdk.amazonaws.com/js/aws-sdk-2.314.0.min.js"></script> <script type="text/javascript"> AWS.config.update( { accessKeyId: "YOUR_ACCESS_KEY", secretAccessKey: "YOUR_SECRET", region: "YOUR_REGION" } ); var s3 = new AWS.S3(); var urlParams = new URLSearchParams(window.location.search); var bucket = urlParams.get('bucket'); var y = urlParams.get('key'); var params = {Bucket: bucket, Key: y}; s3.getSignedUrl('getObject', params, function (err, url) { window.open(url,"_self"); }); </script> </apex:page>

IAM Policy Required for S3 signed URL creation

IAM Policy for IAM user with secret/key used in Visual Force Page s3download.

{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow",

Page 8: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

"Action": "s3:GetObject", "Resource": "arn:aws:s3:::dreamforce-demo-2018/*" } ] }

Lambda Functions

There are 2 Lambda Functions used for this integration. The first lambda function, sfdcDemo_SaasI is used as a long-running (timeout 15 minutes) function that kicked off using a Cloudwatch Event on a Schedule (15 minutes). While the Lambda function is running, it maintains a connection that is Bayeaux protocol with the Cometd event routing bus. For more information: https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/BayeauxProtocolAndCometD.htm

Platform events pushes the event to Lambda and sfdcDemo_SaasI writes the Opp_Id__c from platform event, and publishes it to the configured SNS topic.

Lambda Function sfdcDemo_SaasI

We leverage the nforce node.js library to make the authentication to Salesforce as well as the platform events integration straightforward and easy in node.js. This is a great helper library that does most of the heavy lifting for you when working with Salesforce integration. As this is an external library, you will have to package up the library as part of your Lambda distribution

We use Node.js 8.10 for this. Unfortunately nforce is not compatible with Node.js 8.10 mechanism for asynch processing so we have to use the Promise to make sure things get done in the right order in a predictable fashion.

Also set reserved concurrency to 1. We only want one event to be delivered at a time. If we have multiple Lambda instances running, we will have multiple duplicate SNS messages.

Here is the code:

var nforce = require('nforce'); var AWS = require('aws-sdk'); // All the authenication is part of the configuration for a Connected App in Salesforce var org = nforce.createConnection({ clientId: 'GET THIS FROM SALESFORCE', clientSecret: 'GET THIS FROM SALESFORCE', redirectUri: 'http://localhost:3000/oauth/_callback',

Page 9: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

mode: 'single' }); var TOPIC = 'OppCRUD__e'; var REPLAY_ID = -1; var USERNAME = "YOUR_EMAIL_ADDRESS_AS_USERNAME"; var PASSWORD = "YOUR_PASSWORD"; //SNS TOPIC var TOPIC_ARN = "YOUR_SNS_TOPIC_ARN"; exports.handler = function(event, context, callback) { // authenticate via oauth process to SFDC org.authenticate({ username: USERNAME, password: PASSWORD }, function(err, oauth) { if(err) return console.log("Error authenticating to Salesforce, " + err); var client = org.createStreamClient(); var accs = client.subscribe({topic:TOPIC, isEvent:true, retry: REPLAY_ID}); //if Subscription fails, function will disconnect before this console.log("Subscription to " + TOPIC + " successful"); // When an error occurs as it receives an event accs.on('error', function(err) { console.log('Error occurred, ' + err); client.disconnect(); }); // When data is received, this is executed // SNS Message only has the OppID // console.logs for debugging purposes accs.on('data', function(data) { console.log("Platform event on topic, " + TOPIC + " detected\nEvent:" + JSON.stringify(data.payload)); var opp_id = data.payload.OppId__c; var params = { Message: JSON.stringify(data.payload), TopicArn: TOPIC_ARN }; // Create promise and SNS service object var publishTextPromise = new AWS.SNS({apiVersion: '2010-03-31'}).publish(params).promise(); // Handle promise's fulfilled/rejected states publishTextPromise.then( function(data) { console.log(`Message sent to the topic ${params.TopicArn}`); console.log("MessageID is " + data.MessageId); }).catch( function(err) { console.error(err, err.stack); });

Page 10: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

}); //end of data event }); //end of org auth };

Permissions:

Basic Execution permissions for Lambda Give Lambda access to the SNS topic used to trigger actions when a platform event is

detected. If leveraging PrivateLink for private communication, permissions required for Lambda

VPC access

Lambda Function sfdcDemo_Example1

When a message is published to a SNS topic, all subscribed endpoints will get triggered with the OppId as the payload. In this demo, we created two Lambda functions to show a fan-out pattern. One Lambda function simply logged the result to Cloudwatch (not shown). This Lambda function sfdcDemo_Example1 is triggered when sfdcDemo_SaasI publishes the OppId message to SNS. It uses the exact same nforce helper library as well as the same authentication code because it has the job of querying Salesforce for more of the Opportunity Object. The results of this query will be stored in s3 and acts as an archive of the Opportunity as it is updated. This can then be queried later on by Athena via SQL.

var nforce = require('nforce'); var AWS = require('aws-sdk'); // All the authenication is part of the configuration for a Connected App in Salesforce var org = nforce.createConnection({ clientId: 'GET THIS FROM SALESFORCE', clientSecret: 'GET THIS FROM SALESFORCE', redirectUri: 'http://localhost:3000/oauth/_callback', mode: 'single' }); var oauth; var REPLAY_ID = -1; var USERNAME = "YOUR_EMAIL_ADDRESS_AS_USERNAME"; var PASSWORD = "YOUR_PASSWORD"; var bucketname = "S3_BUCKET_FOR_YOUR_OpportunityArchive_AND_Attachments"; exports.handler = function(event, context, callback) { org.authenticate({ username: USERNAME, password: PASSWORD }, function(err, oauth) { if(err) return console.log("Error authenticating to Salesforce, " + err); //SNS trigers this Lambda function and is sent as part of the event var opp_id = JSON.parse(event.Records[0].Sns.Message).OppId__c; //Query for Opportunity record for version archival purposes

Page 11: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

var oppquery = "Select Id, Name, Account.Name, Type, LeadSource, StageName, Probability, CloseDate, Amount, CreatedBy.Name, LastModifiedBy.Name from Opportunity where Id='" + opp_id + "'"; //function that queries Salesforce for the Opportunity Object //put Opportunity information into an s3 bucket as a csv querySFDC(oppquery) .then((myresult) => { console.log(myresult); var oppstring = myresult.get("Id") + "," + myresult.get("Name") + "," + getDeep(myresult,"account.Name") + "," + myresult.get("Type") + "," + myresult.get("LeadSource") + "," + myresult.get("StageName") + "," + myresult.get("Probability") + "," + myresult.get("CloseDate") + "," + myresult.get("Amount") + "," + getDeep(myresult,"createdby.Name") + "," + getDeep(myresult,"lastmodifiedby.Name"); console.log ("Opportunity is: " + oppstring); //Put Opp into s3 bucket as a csv var sd = (new Date).getTime(); var attachmentName = opp_id + sd + ".csv"; var s3key = "DataLake/" + attachmentName; var filetype = myresult.get("FileType"); var contentType = "text/csv"; putToS3bucket(oppstring,bucketname,s3key,contentType); }) .catch(error => { console.log("Error occurred in query for record archival purposes."); }); //Query for ContentDocumentId related to OpportunityId //Attachments are not directly part of the Opportunity //When Salesforce attachments are added to an Opportunity, the ContentDocumentLink table stores the reference to Opportunity //Attachment and its metadata are taken from ContentDocument Table var query = "SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = '" + opp_id + "'"; querySFDC(query) .then((myresult) => { var query = "Select LatestPublishedVersionId,Title,FileType from ContentDocument Where ID = '" + myresult.get("ContentDocumentId") + "'"; return querySFDC(query); }) .then((myresult) => { var id = myresult.get("LatestPublishedVersionId"); var attachmentName = myresult.get("Title"); var s3key = "Opportunities/" + opp_id + "/ContentData/" + attachmentName; var filetype = myresult.get("FileType");

Page 12: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

var contentType; var extension; if (filetype=="PDF") { contentType = "application/pdf"; extension = "pdf"; } else { contentType="image/jpeg" extension="jpg"; } var s3filename = attachmentName + "." + extension; var s3url = "https://s3.amazonaws.com/" + bucketname + "/" + s3key; //calls function to grab attachment and put it to s3 bucket getContentDataArchiveToS3bucket(id,bucketname,s3key,contentType); //calls function to update Salesforce Opportunity with metadata about file uploaded to s3 updateSFDC(opp_id,bucketname,s3url,s3key,s3filename); }) .catch(error => { console.log("Error catch from promise section - maybe no records."); }); }); }; //This function queries Salesforce and returns the result function querySFDC(query) { return new Promise( function (resolve, reject) { var queryresult; console.log("Query Running: " + query); org.query({ query: query }) .then(function(results) { if (results.records.length > 0) { queryresult=results.records[0]; } else { console.log("Returned No records"); reject("There are no attachments"); } resolve(queryresult); }).error(function(error) { var errorOutput = 'ERROR: Query failed for with error:' + error; reject(errorOutput); }); }); } // This function uploads an Opportunity Object stored as a string in a csv to s3 function putToS3bucket(somestring, bucketname,s3key,contentType) { var s3Bucket = new AWS.S3(

Page 13: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

{ params: {Bucket: bucketname} }); var data = { Key: s3key, Body: somestring, ContentType: contentType }; s3Bucket.putObject(data, function(err, data){ if (err) { console.log(err); console.log('Error: ' + err + ' while uploading some String to S3: ' + data); } else { console.log('Succesfully uploaded the some String file to S3 with key, ' + s3key); } }); } //This function gets the Attachment file from the ContentVersionData table and uploads to S3. It uses a function from nforce called getContentVersionData. function getContentDataArchiveToS3bucket(id,bucketname,s3key,contentType) { org.getContentVersionData({id: id}) .then(function(myresult) { console.log("Starting upload process to S3"); var s3Bucket = new AWS.S3( { params: {Bucket: bucketname} }); //Strips out the data portion, preparing the file for s3 upload as base64 object myresult.imageBinary.replace(/^data:image\/\w+;base64,/, ""),'base64') var buf = new Buffer(myresult,'base64'); var data = { Key: s3key, Body: buf, ContentEncoding: 'base64', ContentType: contentType }; s3Bucket.putObject(data, function(err, data){ if (err) { console.log(err); console.log('Error: ' + err + ' while uploading data to S3: ' + data); } else { console.log('Succesfully uploaded the file to S3 with key, ' + s3key); } }); }); }

Page 14: Amazon Software License · Events, was to send myself an email on a change. Custom Lightning Components Here are the Lightning Components and their code: To create a Lightning Component,

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

// Licensed under the Amazon Software License

// http://aws.amazon.com/asl/

// Uses helped object to create an updated Opportunity SObject and update Salesforce with the new Opportunity information function updateSFDC(oppid,s3bucket,s3url,s3key,s3filename) { var obj = nforce.createSObject('Opportunity', { S3_Archival_URL__c: s3url, s3key__c: s3key, s3filename__c: s3filename, s3bucket__c: s3bucket }); obj.setId(oppid); org.update({ sobject: obj, oauth: oauth }, function(err, res) { if(err) { console.log("res?" + res); console.log("error?" + err); } console.log("Successfully updated the SFDC record"); }); } // nforce doesn't handle objects that are more than 2 levels deep. This is an addition function to get another level deeper into a Salesforce object function getDeep(record, field) { if(field) { if (field.indexOf(".")!=-1) { var ar = field.split("."); var zleft = ar[0]; var zright = ar[1]; var levelone = record._fields[zleft] var leveltwo = levelone[zright]; return leveltwo; } else { return record._fields[field]; } } };

Permissions:

Basic Execution permissions for Lambda Give Lambda access to write to the S3 bucket and key If leveraging PrivateLink for private communication, permissions required for Lambda

VPC access to S3 VPC Endpoint for example.


Recommended