Skip to content

Commit

Permalink
Merge pull request #6 from transcend-io/bencmbrook-patch-1
Browse files Browse the repository at this point in the history
Update README and examples to show changes
  • Loading branch information
bencmbrook authored Sep 28, 2020
2 parents e9c8237 + b34b155 commit 1dbfa7b
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 67 deletions.
40 changes: 22 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
# examples
# Examples

Some examples of how to integrate with transcend in various languages. See [our documentation](https://docs.transcend.io/) for further information.
Some examples of how to integrate with Transcend in various languages. See [our documentation](https://docs.transcend.io/) for further information.

## What are these examples

These examples are meant to show you what the integration will look like when you connect your internal systems to transcend.
These examples are meant to show you what the integration will look like when you connect your internal systems to Transcend.

Each language has an example of how to:

- Verify a webhook that is sent from transcend ([docs](https://docs.transcend.io/docs/receiving-webhooks))
- How to perform identity enrichment by responding to a webhook ([docs](https://docs.transcend.io/docs/identity-enrichment))
- How to respond to ACCESS/ERASURE and other DSR webhooks ([docs](https://docs.transcend.io/docs/responding-to-dsrs))
- Verify a webhook that is sent from Transcend ([docs](https://docs.transcend.io/docs/receiving-webhooks))
- Respond to ACCESS/ERASURE and other DSR webhooks ([docs](https://docs.transcend.io/docs/responding-to-dsrs))

The JavaScript folder also has an example of how to:

- Perform identity enrichment by responding to a webhook ([docs](https://docs.transcend.io/docs/identity-enrichment))

Using [ngrok](https://ngrok.com/) you can actually [connect these examples](https://app.transcend.io/data-map/silos?integrationName=server) to your [datamap](https://app.transcend.io/data-map).

## Try it in your environment

To configure these example, you will need to create a file named `.env` and fill it out with your configuration
To configure these examples, you will need to create a file named `.env` and fill it out with your configuration.

```sh
TRANSCEND_API_KEY="<TODO>"
Expand All @@ -32,27 +35,28 @@ API keys must be scoped to certain operations or data silos.

### SOMBRA_API_KEY

This API key authenticates you to to your sombra gateway.
This API key authenticates you to to your Sombra gateway.

- If you are self hosting sombra, you would have generated this at time of setup and stored it securely.
- If transcend is hosting the gateway on your behalf, you should have received this via some secure channel
- If you're using multi-tenant Sombra (most common) you don't need to set this.
- If you are self-hosting Sombra, you would have generated this at the time of setup and stored it securely.
- If Transcend is hosting the gateway on your behalf in a single-tenant instance, you will receive this via a secure channel.

### ORGANIZATION_URI

This is the unique uri of your organization on transcend found [here](https://app.transcend.io/settings#OrganizationSettings).
This is the unique URI of your organization on Transcend, found [here](https://app.transcend.io/settings#OrganizationSettings).

### SOMBRA_URL

This is the URL of your sombra gateway.
This is the URL of your Sombra gateway.

- If you are self hosting, you assign this value
- If transcend is hosting, it is often at `https://<ORGANIZATION_URI>.sombra.transcend.io`
- If you're using multi-tenant Sombra (most common), this is `https://multi-tenant.sombra.transcend.io`.
- If you are self-hosting Sombra, you assign this value.
- If Transcend is hosting the gateway on your behalf in a single-tenant instance, this is `https://<ORGANIZATION_URI>.sombra.transcend.io`.

## Languages

Check out your language of choice for further details

- [javascript](./javascript)
- [python](./python)
- [ruby](./ruby)
- [typescript](./typescript)
- [JavaScript](./javascript)
- [Python](./python)
- [Ruby](./ruby)
19 changes: 3 additions & 16 deletions javascript/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Javascript
# JavaScript

Internal system integrations in JavaScript. Check out the parent [README](../README.md) for more context.

Expand All @@ -14,23 +14,10 @@ yarn
yarn start
```

## Open the browser

Go to [https://localhost:4445](https://localhost:4445)

## Add to your datamap

You can test against this example live by adding it to [your datamap](https://app.transcend.io/data-map/silos?integrationName=server) and using [ngrok](https://ngrok.com/) to map your localhost to a live domain.

```sh
ngrok http -hostname=test-javascript.ngrok.io 4445
```

## Transcend developer notes
## Transcend-internal developer notes

- This code is actively used for live demos.
- This is associated with the demo account, [eShopIt](https://e-shop-it.trsnd.co).
- It is hosted on [Render](http://render.com/) at <https://transcend-example.onrender.com>.
- A design choice was made not to put webhook verification on an Express middleware. It's a nice refactor, but it can be esoteric to readers.

- Use ngrok
- Use ngrok in dev.
6 changes: 6 additions & 0 deletions javascript/src/constants.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
const {
TRANSCEND_API_KEY,
ENRICHMENT_SIGNING_KEY,
ORGANIZATION_URI,
SOMBRA_API_KEY,
SOMBRA_URL,
PORT,
} = process.env;

module.exports = {
TRANSCEND_API_KEY,
ENRICHMENT_SIGNING_KEY,
ORGANIZATION_URI,
SOMBRA_API_KEY,
SOMBRA_URL: SOMBRA_URL || 'https://multi-tenant.sombra.transcend.io',
PORT: PORT || 8081,
}
1 change: 1 addition & 0 deletions javascript/src/handleDSRWebhook.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ module.exports = asyncHandler(async (req, res, next) => {

case 'ERASURE':
// Respond with an early "no user found" signal.
// TODO: show an erasure PUT request in this example https://docs.transcend.io/docs/responding-to-dsrs#fulfill-an-erasure-request-dser
res.sendStatus(204);
break;

Expand Down
3 changes: 2 additions & 1 deletion javascript/src/helpers/createEnricherJwt.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const jwt = require('jsonwebtoken');
// Constants
const {
ENRICHMENT_SIGNING_KEY,
ORGANIZATION_URI,
} = require('../constants');

// In this example, the signing key is stored as a base64-encoded env var
Expand All @@ -22,7 +23,7 @@ module.exports = function createEnricherJwt(content) {
algorithm: 'ES384',
expiresIn: '1d',
// organization URI from https://app.transcend.io/settings#OrganizationSettings
audience: 'e-shop-it',
audience: ORGANIZATION_URI,
}
)
};
4 changes: 3 additions & 1 deletion javascript/src/helpers/verifyAndExtractWebhook.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const jwt = require('jsonwebtoken');
// Constants
const {
TRANSCEND_API_KEY,
SOMBRA_API_KEY,
} = require('../constants');

// Global to cache the webhook signing public key
Expand All @@ -23,9 +24,10 @@ module.exports = async function verifyAndExtractWebhook(signedToken) {
if (!cachedPublicKey) {
try {
const response = await got.get(
'https://multi-tenant.sombra.transcend.io/public-keys/sombra-general-signing-key', {
`${SOMBRA_URL}/public-keys/sombra-general-signing-key`, {
headers: {
authorization: `Bearer ${TRANSCEND_API_KEY}`,
'x-sombra-authorization': SOMBRA_API_KEY ? `Bearer ${SOMBRA_API_KEY}` : undefined,
},
},
);
Expand Down
8 changes: 6 additions & 2 deletions javascript/src/scheduleAccessRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const pipeline = promisify(stream.pipeline);
// Constants
const {
TRANSCEND_API_KEY,
SOMBRA_API_KEY,
SOMBRA_URL,
} = require('./constants');

// Helpers
Expand All @@ -32,9 +34,10 @@ module.exports = async function scheduleAccessRequest(userIdentifier, nonce, req
const userData = await lookUpUser(userIdentifier);

// Upload in bulk to datapoints, with a JSON payload
const bulkUpload = got.post('https://multi-tenant.sombra.transcend.io/v1/data-silo', {
const bulkUpload = got.post(`${SOMBRA_URL}/v1/data-silo`, {
headers: {
authorization: `Bearer ${TRANSCEND_API_KEY}`,
'x-sombra-authorization': SOMBRA_API_KEY ? `Bearer ${SOMBRA_API_KEY}` : undefined,
'x-transcend-nonce': nonce,
accept: 'application/json',
'user-agent': undefined,
Expand All @@ -46,9 +49,10 @@ module.exports = async function scheduleAccessRequest(userIdentifier, nonce, req

// Upload a file to a datapoint
const readFile = fs.createReadStream(path.join(__dirname, 'media/big_buck_bunny.mp4'));
const fileUpload = got.stream.post('https://multi-tenant.sombra.transcend.io/v1/datapoint', {
const fileUpload = got.stream.post(`${SOMBRA_URL}/v1/datapoint`, {
headers: {
authorization: `Bearer ${TRANSCEND_API_KEY}`,
'x-sombra-authorization': SOMBRA_API_KEY ? `Bearer ${SOMBRA_API_KEY}` : undefined,
'x-transcend-nonce': nonce,
accept: 'application/json',
'user-agent': undefined,
Expand Down
6 changes: 4 additions & 2 deletions python/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@

"""
Get the sombra public key, used to verify the coreIdentifier
TODO: add authentication headers for multi-tenant Sombra in this example
"""
def get_transcend_public_key():
res = requests.get(SOMBRA_URL + '/public-keys/sombra-general-signing-key', verify = not TRUST_SELF_SIGNED_CERT)
Expand Down Expand Up @@ -88,6 +89,7 @@ def get_core_identifier(headers):

"""
Construct the headers to respond to webhooks with
TODO: make x-sombra-authorization optional in this example
"""
def response_headers(response_jwt_token):
return {
Expand Down Expand Up @@ -208,8 +210,8 @@ def do_POST(self):
def main():
# Create https server
httpd = HTTPServer(('localhost', 4443), SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket,
keyfile="ssl/private.key",
httpd.socket = ssl.wrap_socket (httpd.socket,
keyfile="ssl/private.key",
certfile='ssl/certificate.pem', server_side=True)

# Run
Expand Down
3 changes: 3 additions & 0 deletions ruby/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def perform_access(user, nonce)
}

# Signal that it has been completed.
# TODO: make x-sombra-authorization optional in this example
resp = Faraday.post($DATA_SILO_PATH) do |req|
req.headers['Content-Type'] = 'application/json'
req.headers['accept'] = 'application/json'
Expand All @@ -134,6 +135,7 @@ def perform_erasure(user, nonce)
}

# Signal that it has been completed.
# TODO: make x-sombra-authorization optional in this example
resp = Faraday.put($DATA_SILO_PATH) do |req|
req.headers['Content-Type'] = 'application/json'
req.headers['accept'] = 'application/json'
Expand All @@ -145,6 +147,7 @@ def perform_erasure(user, nonce)
end

# Retrieve public key from Sombra
# TODO: add authentication headers for multi-tenant Sombra in this example
def transcend_public_key
response = Faraday.get($PUBLIC_KEY_URL)
OpenSSL::PKey.read(response.body)
Expand Down
27 changes: 0 additions & 27 deletions typescript/README.md

This file was deleted.

0 comments on commit 1dbfa7b

Please sign in to comment.