salesforce/canvas/routers/main.ts (44 lines of code) (raw):

/** * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import crypto from 'crypto'; import dotenv from 'dotenv'; import express from 'express'; import {uuid} from 'uuidv4'; dotenv.config(); const router = express.Router(); const consumerSecret = process.env.CANVAS_CONSUMER_SECRET; const clientId = process.env.CANVAS_CONSUMER_KEY; const proxyServer = process.env.PROXY_URL; /* * handle Canvas signed POST request containing Canvas context and attempt * to decode the request using our Canvas application's consumer secret */ router.post('/', (req, res) => { if (!consumerSecret || !clientId) { res.send('Canvas OAuth settings missing'); } const signedRequest = req.body.signed_request; const [encodedSignature, encodedEnvelope] = signedRequest.split('.'); const check = crypto.createHmac('sha256', consumerSecret) .update(encodedEnvelope) .digest('base64'); if (check !== encodedSignature) { res.send('Signature does not match.'); } const signedRequestJson = JSON.parse(Buffer.from(encodedEnvelope, 'base64').toString('ascii')); const {context, client} = signedRequestJson; const {conversationProfile, features, debug} = req.query; if (!features || typeof features !== 'string') { res.send( 'Error - please provide a features list in the URL query parameters'); return; } if (!conversationProfile || typeof conversationProfile !== 'string') { res.send( 'Error - please provide a conversation profile name in the URL query parameters'); return; } const [, projectLocation] = conversationProfile.match( /(^projects\/[^/]+\/locations\/[^/]+)\/conversationProfiles\/[^/]+$/) || []; if (!projectLocation) { res.send( 'Error - please provide a correctly formatted conversation profile name ' + 'in the URL query parameters. Format: ' + '"projects/<project_id>/locations/<location_id>/conversationProfiles/<conversation_profile_id>"'); return; } // Generate a random conversation ID for demo purposes. In a real app, this // would come from an external source. const conversationId = `a${uuid()}`; const conversationName = `${projectLocation}/conversations/${conversationId}`; res.render('main', { clientId, proxyServer, salesforceToken: client.oauthToken, salesforceContext: context, signedRequestJson, conversationId, conversationProfile, conversationName, features, debug, }); }); export {router as mainRouter};