-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
29 changed files
with
1,373 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[[source]] | ||
name = "pypi" | ||
url = "https://pypi.org/simple" | ||
verify_ssl = true | ||
|
||
[dev-packages] | ||
|
||
[packages] | ||
jinja2 = "*" | ||
pyyaml = "*" | ||
python-slugify = "*" | ||
markdown = "*" | ||
|
||
[requires] | ||
python_version = "3.8" |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<div class=""> | ||
<h1>The DLRS (Declarative Lookup Rollup Summaries) tool</h1> | ||
|
||
<h2>Use cases</h2> | ||
|
||
<ul> | ||
<li>Can't use native rollup summaries.</li> | ||
<li>Job needs to be done by an administrator.</li> | ||
</ul> | ||
|
||
<h2>Considerations</h2> | ||
|
||
<p>The tool has gone through a big migration in the past. It used to use custom settings for managing rollups, but since Salesforce introduced Custom Metadata Types, the tool uses them.</p> | ||
|
||
<h2>Repository</h2> | ||
|
||
<p>The source code can be found <a href="https://github.com/afawcett/declarative-lookup-rollup-summaries/">on GitHub</a>.</p> | ||
|
||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Each project should have the following format: | ||
# | ||
# title: Project's Title | ||
# location: github | ||
# url: github.com/repos/url | ||
|
||
projects: | ||
- | ||
title: Declarative Rollup Summaries for Lookups | ||
description: dlrs.md | ||
location: github | ||
url: https://github.com/afawcett/declarative-lookup-rollup-summaries/ | ||
- | ||
title: Mass Action Scheduler | ||
description: mas.md | ||
location: github | ||
url: https://github.com/douglascayers-org/sfdx-mass-action-scheduler | ||
- | ||
title: Dogeforce's Website (this site!) | ||
description: dogeforce.md | ||
location: github | ||
url: https://github.com/Dogeforce/dogeforce.github.io/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
--- | ||
title: Salesforce’s Apex does not support the PATCH method. What to do if I need to call an endpoint with PATCH? | ||
author: @renatoliveira | ||
publish_date: 2020-12-25 | ||
preview: I needed to call a Microsoft Azure endpoint from Salesforce using the PATCH HTTP verb. The problem is, as mentioned in the title, that Apex does not support this verb. | ||
--- | ||
I had a requirement once. A proof of concept. I needed to call a Microsoft Azure endpoint from Salesforce using the PATCH HTTP verb. The problem is, as mentioned in the title, that Apex does not support this verb. | ||
|
||
If we are trying to call a Salesforce endpoint, there’s a trick: append `?_HttpMethod=PATCH` to the end of the URL. This is a workaround that Salesforce. This doesn’t help us because we are not calling a Salesforce endpoint. Another workaround would be setting the X-HTTP-Method-Override as PATCH in the request’s header. This is a convention that some servers follow, but this does not guarantee that the server being called will accept our request as a patch. | ||
Let’s write a simple proxy that is hosted on Heroku! | ||
|
||
Leveraging a Heroku app in another cloud (technically another Salesforce cloud since 2010) we are able to forward our request to its final destination. | ||
|
||
>1. Salesforce calls our Heroku app endpoint | ||
>2. The app forwards the request with the correct verb | ||
>3. The app receives the response from Azure and forwards it back to Salesforce | ||
To do that, I’m going to use Python with the Flask and requests libraries. Flask will handle the “web app” part, while requests is going to be used to forward our request. | ||
|
||
NOTE: I am not going to cover the part where we get Azure’s access token because that doesn’t involve an unsupported verb. | ||
|
||
Assuming that our Salesforce code will send a request with the access token, the payload and the target URL, it will probably look like this: | ||
|
||
{ | ||
"token": "V2VsbCBhcmVuJ3QgeW91IGN1cmlvdXM/DQoNCiBMb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCwgY29uc2VjdGV0dXIgYWRpcGlzY2luZyBlbGl0LiBOdWxsYW0gcGVsbGVudGVzcXVlIHRvcnRvciBhYyBlbmltIGxhb3JlZXQsIGFjIGVsZW1lbnR1bSB0dXJwaXMgdWx0cmljaWVzLiBJbnRlZ2VyIGludGVyZHVtIHJpc3VzIGxhY3VzLCBlZ2V0IGNvbnNlcXVhdCBsaWd1bGEgZmVybWVudHVtIHZpdGFlLiBFdGlhbSBzb2RhbGVzLCBsaWJlcm8gdml0YWUgZGlnbmlzc2ltIGx1Y3R1cywgbGliZXJvIGFyY3UgdnVscHV0YXRlIHF1YW0sIGF0IG1hdHRpcyBkdWkgbWFnbmEgbmVjIG1hc3NhLiBEb25lYyBpcHN1bSBkb2xvciwgZnJpbmdpbGxhIHZpdGFlIG5pYmggYXQsIHJob25jdXMgc2NlbGVyaXNxdWUgZXN0LiBEb25lYyBuZWMgc29kYWxlcyByaXN1cy4gUGVsbGVudGVzcXVlIHF1aXMgZnJpbmdpbGxhIGVyb3MuIFBlbGxlbnRlc3F1ZSBoYWJpdGFudCBtb3JiaSB0cmlzdGlxdWUgc2VuZWN0dXMgZXQgbmV0dXMgZXQgbWFsZXN1YWRhIGZhbWVzIGFjIHR1cnBpcyBlZ2VzdGFzLiBOYW0gcnV0cnVtIG1ldHVzIG1hdXJpcywgYWMgdWxsYW1jb3JwZXIgdGVsbHVzIGF1Y3RvciBpbi4gVXQgYWNjdW1zYW4gc2NlbGVyaXNxdWUgc29kYWxlcy4gRnVzY2UgdmFyaXVzIG5lcXVlIGVzdCwgc2VkIHB1bHZpbmFyIHNlbSBzY2VsZXJpc3F1ZSBub24uIA==", | ||
"payload": "IFNlZCB2ZW5lbmF0aXMgZXQgbWV0dXMgbm9uIGx1Y3R1cy4gUGVsbGVudGVzcXVlIGFjIGV1aXNtb2QgbWV0dXMsIG5lYyB0ZW1wb3IgZHVpLiBOYW0gYSB2ZXN0aWJ1bHVtIGZlbGlzLiBOdW5jIG1hZ25hIGxpZ3VsYSwgY29uZ3VlIG5lYyBpbXBlcmRpZXQgdXQsIGNvbmd1ZSB2dWxwdXRhdGUgcXVhbS4gTWFlY2VuYXMgYmxhbmRpdCwgZmVsaXMgbmVjIHNlbXBlciBkYXBpYnVzLCB0ZWxsdXMgaXBzdW0gdm9sdXRwYXQgYXVndWUsIGFjIGVnZXN0YXMgbmlzbCBvcmNpIG5lYyBzYXBpZW4uIEV0aWFtIGEgdnVscHV0YXRlIGVyb3MuIEN1cmFiaXR1ciBsYWNpbmlhIHNjZWxlcmlzcXVlIG5pc2wgc2VkIHZvbHV0cGF0LiBNYXVyaXMgdml0YWUgZXJhdCBwZWxsZW50ZXNxdWUsIGxhY2luaWEgdHVycGlzIHV0LCB0ZW1wb3Igc2FwaWVuLiBJbnRlZ2VyIHZlbCBsb2JvcnRpcyBkdWkuIEN1cmFiaXR1ciBpbXBlcmRpZXQgbWF0dGlzIGZlbGlzLiBQaGFzZWxsdXMgY29tbW9kbyBtYXNzYSBldSB2ZWxpdCBkYXBpYnVzIHRyaXN0aXF1ZSBhIGV1IGxpYmVyby4gRnVzY2UgaW4gcmlzdXMgZW5pbS4gRnVzY2UgZmVybWVudHVtIGV0IHB1cnVzIGV0IGNvbmRpbWVudHVtLiBJbiBzY2VsZXJpc3F1ZSBwb3N1ZXJlIGVsaXQsIHZpdGFlIGludGVyZHVtIHR1cnBpcyBjb25zZWN0ZXR1ciBhdC4g", | ||
"url": "https://outlook.office.com/api/beta/me/contacts/31d14663-8cf4-4acf-b1c8-556b8e62107d" | ||
} | ||
|
||
The app will receive this and interpret it as “okay, I’ve got this encoded payload, and I shall use this token to send it to this endpoint”: | ||
|
||
# Import the required libraries | ||
# Flask is the web framework for dealing with web stuff (such as serving the app and handling | ||
# the connections) We need to import the main "Flask" to run the app, and also its | ||
# request and Response method and class to handle the request properly | ||
from flask import Flask, Response, request | ||
|
||
# requests is a simple http request library to handle... requests. | ||
import requests | ||
|
||
# Base64 is a standard module to help us encode/decode Base 64 strings | ||
import base64 | ||
# Json is a standar dmodule to help us handle JSON in Python (converting it from/to | ||
# dictionaries - which are also known as maps in some other languages) | ||
import json | ||
# OS is a standard module to handle dealing with the OS directly (we use it just to check | ||
# an environment variable at the end of the script) | ||
import os | ||
|
||
|
||
# Lets first create the app. This is an empty app which does nothing. | ||
# The app will do what we want as we define the methods/routes below, with (for example) | ||
# the `app.route` decorator (which specifies the route and allowed methods) | ||
app = Flask(__name__) | ||
|
||
# This route defines that the app can receive POST requests in the `/contact/` endpoint. So | ||
# when deployed, if the app is named `quiet-waters-12345`, its Heroku URL will be | ||
# `https://quiet-waters-12345.herokuapp.com/` and we should hit that endpoint, adding the | ||
# `/contact/` at the end. | ||
@app.route('/contact/', methods=['POST']) | ||
def contact(): | ||
# First lets deserialize the request's JSON data into a dictionary. | ||
request_data = request.get_json() | ||
|
||
# We check if there are the required attributes we need | ||
if 'token' in request_data and 'payload' in request_data and 'url' in request_data: | ||
try: | ||
# We try to decode the payload | ||
payload = base64.b64decode(request_data['payload']).decode('utf-8') | ||
|
||
# Assign the original payload to a new attribute named `original_payload` | ||
# in our dictionary | ||
request_data['original_payload'] = payload | ||
|
||
# Define the headers as required by the Azure endpoint | ||
headers = { | ||
'Authorization': 'Bearer ' + request_data['token'], | ||
'Content-Type': 'application/json' | ||
} | ||
|
||
# Try to call external endpoint using the requests library. Note that we | ||
# use the `patch` method here. | ||
azure_request = requests.patch( | ||
url=request_data['url'], | ||
data=payload, | ||
headers=headers | ||
) | ||
# When the request is finished, its result is stored in `azure_request`, | ||
# which we can use to get the JSON response. | ||
result = { | ||
"azure_response": azure_request.json() | ||
} | ||
# We basically dump the request's result into a new Response and we return | ||
# it to the service who called us in the first place. | ||
resp = Response(json.dumps(result), status=azure_request.status_code, mimetype='applcation/json') | ||
return resp | ||
except Exception as e: | ||
resp = Response(json.dumps({'error': e.args}), status=500, mimetype='applcation/json') | ||
|
||
# Returns an error response because there is missing data in the payload. | ||
return Response(json.dumps({'error':'No token or payload data informed'}), status=400, mimetype='application/json') | ||
|
||
# Checks if the `IS_HEROKU` variable is set. If it is (in our dyno) then the app is running on | ||
# Heroku's cloud. Otherwise it is running locally in our machine, so we want it to run in our | ||
# localhost, on port 8080 instead (and with debug mode active). | ||
if not os.environ.get('IS_HEROKU', None) and __name__ == '__main__': | ||
app.run(host='localhost', port='8080', debug=True) | ||
|
||
And with this small web app hosted in Heroku we are not limited to a single URL. This transforms any POST request to a PATCH request. I’ve used this to call an Outlook endpoint (hence why the apps’ route was named /contacts/) but it can be renamed as needed. | ||
|
||
An idea would be to have all HTTP verbs available as endpoints, such as /post, /get, /delete, etc. This way the app will look more like an endpoint bus though… |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
## About the tool | ||
|
||
The DLRS is a tool that offers a feature set that extends a feature called "rollup summaries" on the Salesforce platform. It deploys Apex code to your organization and enables administrators to deploy automatically generated code to the org (even a production environment, yes). | ||
|
||
The tool code operates using custom metadata records managed by a Visualforce page on the project. From there an administrator or a developer can create custom metadata records for the tool to use when running its triggers (the code deployed which was mentioned before). | ||
|
||
When a record with a DLRS trigger is saved, it activates the DLRS tool which then gets the custom setting for the specific object. Then it queries the object and its related record(s) to update its rollup summary. | ||
|
||
### Example | ||
|
||
A rollup is created on Custom Object A (`CustomObjectA__c`) to count how many Custom Object B's (`CustomObjectB__c`) records are related to it through a common lookup field (not a master-detail relationship, that is). | ||
|
||
When a new object B is created, updated or deleted, the tool analyzes the criteria defined on its custom setting (the custom metadata type) and evaluates whether or not to update the counter on the parent (object A) field. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
## About this site | ||
|
||
This is an open-source website with the goal to aggregate Salesforce resources such as open source projects (like the DLRS or the Mass Action Scheduler) and comment about them, talk about their use cases, but mostly because the creator had too much free time on a weekend. | ||
|
||
You can check out the source code at the github repository in the link above. This website is hosted at GitHub as well. It's source is generated by a Python script that gathers the sources from many folders and "compiles" them to HTML which is then served by GitHub. The script is also custom made too (which is why it might look a little too ugly - *PR's are welcome*). | ||
|
||
### Contributing | ||
|
||
This website's source is open [on GitHub](https://github.com/Dogeforce/dogeforce.github.io/), so anyone with Python 3.8+ installed can contribute (because it is necessary to generate the files locally and push them). Just create a pull request with the content or improvements to the site's (like the CSS). The project uses [Pipenv](https://pipenv.pypa.io/en/latest/) to manage dependencies, so one can easily create a virtual Python environment to use the libraries (the four packages listed on the Pipfile). | ||
|
||
To write an article, create the markdown file inside the `content > source > posts` folder, and do not forget to add the metadata information on the beginning of the file, such as: | ||
|
||
--- | ||
title: The title of the article | ||
author: your @ on github or maybe twitter (or none) | ||
publish_date: 2020-12-25 | ||
preview: A small text explaining what the article is about | ||
--- | ||
|
||
Then you can use the `make build` command to generate the necessary files. The script reads the files inside the `content > source > posts` folder and turns them into `.html` files on the `posts` folder. Alternatively, if there is no `make` command available one just needs to run the `src/scripts/main.py` file with `python` from the root folder. | ||
|
||
It is possible to preview the content using `make serve` to start a simple http server on the folder, so one is able to access a site version locally. | ||
|
||
### The Doge logo | ||
|
||
This amazing image was made by a member of the Salesforce Discord Exchange (SFXD). Even stickers were made of it: | ||
|
||
![](/images/no_logs_no_crime.jpg) | ||
|
||
Can you imagine being at a meeting with this guy looking at ya? | ||
|
||
![](/images/sticker_on_laptop.jpg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
## A quote from the project itself: | ||
|
||
>Mass Action Scheduler is a free-as-in-speech and open source developed passion project of Doug Ayers. | ||
And its goal is to give administrators the power to use Batch Apex's power, which is mostly in the hands of developers. | ||
|
||
With this tool an administrator can declaratively schedule a series of process automations (such as email alerts, workflow rules and flows). |
Oops, something went wrong.