Skip to content

Instantly share code, notes, and snippets.

@pcon
Last active May 23, 2016 15:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcon/54e8b0d7518d8fe42c79 to your computer and use it in GitHub Desktop.
Save pcon/54e8b0d7518d8fe42c79 to your computer and use it in GitHub Desktop.
My Bash setup
#Add to .bashrc_sfdc
if [ -f $HOME/.bashrc_sfdc ]
then
. $HOME/.bashrc_sfdc
fi
# Name this .bashrc_sfdc
export SFDC_APIVER="33.0"
export SFDC_PROD_USER="user@example.com"
export SFDC_PROD_PASS="1234password"
export SFDC_PROD_SAND=false
export SFDC_DEV_USER="user@example.com.dev"
export SFDC_DEV_PASS="1234password"
export SFDC_QA_USER="user@example.com.qa"
export SFDC_QA_PASS="1234password"
export SFDC_PERSONAL_USER="user@example.com.personal"
export SFDC_PERSONAL_PASS="1234password"
export SFDC_PERSONAL_SAND=false
alias jsforce_prod="jsforce -u \"$SFDC_PROD_USER\" -p \"$SFDC_PROD_PASS\""
alias jsforce_dev="jsforce --sandbox -u \"$SFDC_DEV_USER\" -p \"$SFDC_DEV_PASS\""
alias jsforce_qa="jsforce --sandbox -u \"$SFDC_QA_USER\" -p \"$SFDC_QA_PASS\""
alias jsforce_personal="jsforce -u \"$SFDC_PERSONAL_USER\" -p \"$SFDC_PERSONAL_PASS\""
alias jsforce_sandbox="jsforce --sandbox -u \"$SFDC_USER\" -p \"$SFDC_PASS\""
function echoerr() {
>&2 echo -e "$@"
}
function setsfdcvars() {
SFDC_HOST=${1^^}
if [ -z $SFDC_HOST ]
then
SFDC_HOST='PROD'
fi
if [ $SFDC_HOST == 'PROD' ]
then
SFDC_SANDBOX=false
else
SFDC_SANDBOX=true
fi
UVAR="SFDC_${SFDC_HOST}_USER"
PVAR="SFDC_${SFDC_HOST}_PASS"
SVAR="SFDC_${SFDC_HOST}_SAND"
export SFDC_USER=${!UVAR}
export SFDC_PASS=${!PVAR}
if [ ".${!SVAR}" != "." ]
then
SFDC_SANDBOX=${!SVAR}
fi
}
function soap_login() {
setsfdcvars $1
LOGIN_FILE="/tmp/login.xml"
SFDC_ENDPOINT="https://login.salesforce.com"
if [ $SFDC_SANDBOX == true ]
then
SFDC_ENDPOINT="https://test.salesforce.com"
fi
curl -s -H 'Content-Type: text/xml' -H 'SOAPAction: ""' -X POST -d "<se:Envelope xmlns:se=\"http://schemas.xmlsoap.org/soap/envelope/\"><se:Header/><se:Body><login xmlns=\"urn:partner.soap.sforce.com\"><username>$SFDC_USER</username><password>$SFDC_PASS</password></login></se:Body></se:Envelope>" "$SFDC_ENDPOINT/services/Soap/u/$SFDC_APIVER" > $LOGIN_FILE
export SFDC_SESSIONID=`cat $LOGIN_FILE | xmllint --xpath "//*[name()='sessionId']/text()" -`
export SFDC_SERVERURL=`cat $LOGIN_FILE | xmllint --xpath "//*[name()='serverUrl']/text()" - | sed 's/\/Soap.*$//'`
rm $LOGIN_FILE
}
function print_status_code() {
STATUS_CODE=$1
MSG=""
if [ ! -z "$2" ]
then
MSG=" - $2"
fi
case $STATUS_CODE in
200)
echoerr "[${GREEN}OK${NC}] $STATUS_CODE$MSG\n"
;;
*)
echoerr "[${RED}BAD${NC}] $STATUS_CODE$MSG\n"
;;
esac
}
function sfdc_curl() {
if [ $# -lt 1 ]
then
echo "Usage: sfdc_curl \"path\" [sandbox]"
return 1
fi
soap_login $2
OUTFILE="TMP_$RANDOM"
HEADERFILE="TMP_$RANDOM"
URI=`echo "$1" | sed 's/^\///'`
MSG_HEADER="Message"
STATUS_CODE=`curl -s -D $HEADERFILE -o $OUTFILE -w "%{http_code}" -H "Authorization: Bearer $SFDC_SESSIONID" -H "Content-Type: application/json" "$SFDC_SERVERURL/apexrest/$URI"`
HEADER_MSG=""
if [ -e $HEADERFILE ]
then
HEADER_MSG=`cat $HEADERFILE | sed -En "s/^$MSG_HEADER: (.*)/\1/p"`
rm $HEADERFILE
fi
print_status_code $STATUS_CODE "$HEADER_MSG"
if [ -e $OUTFILE ]
then
cat $OUTFILE
rm $OUTFILE
fi
}
function getFieldList() {
OBJ_NAME=$1
setsfdcvars $2
if [ $SFDC_SANDBOX == true ]
then
jsforce --sandbox -u "$SFDC_USER" -p "$SFDC_PASS" -e "describe('$OBJ_NAME')" | jq '[.fields[].name] | join(",")' | sed 's/"//g'
else
jsforce_prod -e "describe('$OBJ_NAME')" | jq '[.fields[].name] | join(",")' | sed 's/"//g'
fi
}
function getObject() {
if [ $# -lt 2 ]
then
echo "Usage: getObject objectName Id [sandbox]"
return 1
fi
OBJ_NAME=$1
ID=$2
setsfdcvars $3
FIELDS=$(getFieldList $OBJ_NAME $3)
if [ $SFDC_SANDBOX == true ]
then
jsforce --sandbox -u "$SFDC_USER" -p "$SFDC_PASS" -e "query(\"select $FIELDS from $OBJ_NAME where Id = '$ID'\")" | jq '.records[] | del(.attributes)'
else
jsforce_prod -e "query(\"select $FIELDS from $OBJ_NAME where Id = '$ID'\")" | jq '.records[] | del(.attributes)'
fi
}
function getObjectByParent() {
if [ $# -lt 3 ]
then
echo "Usage: getObjectByParent objectName parentField parentId [sandbox]"
return 1
fi
OBJ_NAME=$1
PARENT_FIELD=$2
ID=$3
setsfdcvars $4
FIELDS=$(getFieldList $OBJ_NAME $4)
if [ $SFDC_SANDBOX == true ]
then
jsforce --sandbox -u "$SFDC_USER" -p "$SFDC_PASS" -e "query(\"select $FIELDS from $OBJ_NAME where $PARENT_FIELD = '$ID'\")" | jq '[.records[] | del(.attributes)]'
else
jsforce_prod -e "query(\"select $FIELDS from $OBJ_NAME where $PARENT_FIELD = '$ID'\")" | jq '[.records[] | del(.attributes)]'
fi
}

#About This is part of my customized .bashrc that I use daily for help with Salesforce work

#Prerequisites Install the following utilities

  • jq - A super handy json parser
  • xmllint - An xml linter and parser
  • jsforce - A great tool for working with Salesforce on the commandline
  • Make sure you install it with npm -g install jsforce

#Installation

  1. Copy the contents of .bashrc_sfdc to your $HOME directory
  2. Add the snippet to your .bashrc to include it

NOTE: I put this in a separate file so that I can keep it out of source control and keep it on my work machine. There is no technical reason to separate them so you can put it all in one file if desired.

#Configuration

  • Update the export lines to contain your usernames and passwords
  • Add new environments by following the pattern of SFDC_{NAME}_USER and SFDC_{NAME}_PASS
  • Add new jsforce aliases for each environment easier use

#Usage

soap_login

This method logs in via the Salesforce SOAP endpoint and set the SFDC_SESSIONID and SFDC_SERVERURL variables for later use

sfdc_curl

This method calls APEX REST methods via cURL.

Apex Definition

@RestResource(urlMapping='/myClass/case/*')
global with sharing class REST_MyClass_Case {
    @HttpGet
    global static Case getCase() {
        Case c = null;
        String caseNumber = RestContext.request.params.get('caseNumber');
        
        List<Case> cases = [
            select Subject
            from Case
            where CaseNumber = :caseNumber
        ];
        
        if (cases.size() != 1) {
            RestContext.response.statusCode = 404;
            RestContext.response.addHeader('Message', 'Unable to find case by number');
        } else {
            c = cases.get(0);
        }
    }
}

Get case in production

sfdc_curl "/myClass/case/?caseNumber=012345"

Get case in dev

sfdc_curl "/myClass/case/?caseNumber=012345" dev

##getObject Get case in production

getObject Case 50011000003bJSJAA2

Get case in dev

getObject Case 50011000003bJSJAA2 dev

##getObjectByParent Get comments for case in production

getObjectByParent CaseComment Parent 50011000003bJSJAA2

Get comments for case in dev

getObjectByParent CaseComment Parent 50011000003bJSJAA2 dev
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment