From ff3d98e3e2dcadc75e51c7422d0af35f0c2ad376 Mon Sep 17 00:00:00 2001 From: pan261 Date: Tue, 8 Feb 2022 22:43:53 -0500 Subject: [PATCH] running ngrok in docker --- docker-compose.yml | 9 ++++++++ package.json | 2 +- src/forge-webhooks.ts | 18 +++++++-------- src/{ => old}/ngrok_script.js | 0 src/server.ts | 41 ++++++++++++++++++++++++++++++----- 5 files changed, 55 insertions(+), 15 deletions(-) rename src/{ => old}/ngrok_script.js (100%) diff --git a/docker-compose.yml b/docker-compose.yml index cf03a0e..42b5ff5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,14 @@ version: "3.8" services: + ngrok: + image: wernight/ngrok:latest + ports: + - 4040:4040 + environment: + NGROK_PROTOCOL: http + NGROK_PORT: server:3000 + NGROK_AUTH: ${NGROK_AUTH} # access through `psql -h localhost -p 5432 -d filesync -U user`, password is 'pass' # to be able to build after the initializing the db, you may need to run `sudo chown -R $USER db_data/` @@ -19,6 +27,7 @@ services: dockerfile: Dockerfile depends_on: - database + - ngrok env_file: ./.env volumes: - ./src/build:/ffs/ diff --git a/package.json b/package.json index b2779b7..66b41bf 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "start:ngrok": "ngrok http 3000", "test": "echo \"Error: no test specified\" && exit 1", "build": "npm run open:page && npm run build:docker", - "build:docker": "node src/ngrok_script.js && tsc --build && docker-compose up --build --remove-orphans", + "build:docker": "tsc --build && docker-compose up --build --remove-orphans", "open:page": "opener http://localhost:3000/auth" }, "repository": { diff --git a/src/forge-webhooks.ts b/src/forge-webhooks.ts index 545d3ea..245616d 100644 --- a/src/forge-webhooks.ts +++ b/src/forge-webhooks.ts @@ -21,8 +21,8 @@ const fileShareID = "urn:adsk.wipprod:fs.folder:co.T0n0mYQeS16K0lq1VuuYVQ"; /** * Function to manage hook lifecycle */ -exports.setupHooks = (credentials: ForgeSDK.AuthToken) => { - console.log("checking hooks"); +exports.setupHooks = (callbackUrl: string, credentials: ForgeSDK.AuthToken) => { + console.log("Checking hooks"); axios.default({ method: "GET", url: "https://developer.api.autodesk.com/webhooks/v1/hooks", @@ -36,7 +36,7 @@ exports.setupHooks = (credentials: ForgeSDK.AuthToken) => { for (var index in data) { const hook = data[index]; - if (hook.callbackUrl != config.hookCallbackURL) { + if (hook.callbackUrl != callbackUrl) { // hooks with invalid callbacks will be deleted, not added to current list of hooks deleteHook(hook.event, hook.hookId, credentials); } else { @@ -50,15 +50,15 @@ exports.setupHooks = (credentials: ForgeSDK.AuthToken) => { // these are the events we want, if not in the list, then register the hook if (!hookEvents.includes("dm.version.added")) { - createHook("dm.version.added", credentials); + createHook("dm.version.added", callbackUrl, credentials); } if (!hookEvents.includes("dm.version.modified")) { - createHook("dm.version.modified", credentials); + createHook("dm.version.modified", callbackUrl, credentials); } if (!hookEvents.includes("dm.version.deleted")) { - createHook("dm.version.deleted", credentials); + createHook("dm.version.deleted", callbackUrl, credentials); } }) .catch((err: axios.AxiosError) => { @@ -66,7 +66,7 @@ exports.setupHooks = (credentials: ForgeSDK.AuthToken) => { }); }; -const createHook = (event: string, credentials: ForgeSDK.AuthToken) => { +const createHook = (event: string, callbackUrl: string, credentials: ForgeSDK.AuthToken) => { axios.default({ method: "POST", url: `https://developer.api.autodesk.com/webhooks/v1/systems/data/events/${event}/hooks`, @@ -76,14 +76,14 @@ const createHook = (event: string, credentials: ForgeSDK.AuthToken) => { }, data: { autoReactivateHook: "true", - callbackUrl: config.hookCallbackURL, + callbackUrl: callbackUrl, scope: { folder: fileShareID, }, }, }) .then((res: axios.AxiosResponse) => { - console.log("sucessfully created hook for " + event); + console.log("Sucessfully created hook for " + event); }) .catch((err: axios.AxiosError) => { err.response && console.log("error creating hook for " + event + ": " + err.response.status); diff --git a/src/ngrok_script.js b/src/old/ngrok_script.js similarity index 100% rename from src/ngrok_script.js rename to src/old/ngrok_script.js diff --git a/src/server.ts b/src/server.ts index b3a244c..0788e38 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,11 +1,13 @@ import express = require("express"); import bodyParser = require("body-parser"); +import * as axios from 'axios'; import * as crypto from "crypto"; import * as config from "./config"; import * as db from "./db"; import * as ForgeSDK from "forge-apis"; import { Request, Response, ErrorRequestHandler } from "express"; +import { resolve } from "path/posix"; const webhooks = require("./forge-webhooks"); const downloader = require("./forge-download"); @@ -60,6 +62,28 @@ app.use( }) ); +const getWebhookCallbackURL = () => { + return axios.default({ + method: "GET", + url: "http://ngrok:4040/api/tunnels", + }) + .then((res: axios.AxiosResponse) => { + let data = res.data.tunnels; + let url: string = ""; + data.forEach((entry: any) => { + if (entry.name === "command_line (http)") { + url = entry.public_url + "/hook" + console.log("Webhook callback url is:", url); + } + }); + + return url; + }) + .catch((err: axios.AxiosError) => { + console.log("ngrok server error:", err.code, err.message); + }); +} + /** * Creates server with three endpoints: * 1. /auth @@ -71,6 +95,7 @@ app.use( * @returns express server object */ const createServer = () => { + const PORT = config.port || 3000; if (config.forgeClientId == null || config.forgeClientSecret == null) { @@ -100,9 +125,12 @@ const createServer = () => { "\x1b[0m/callback reached, token generated" ); }) - .then(() => { + .then(async () => { + // get webhook callback url from ngrok + let webhookUrl = await getWebhookCallbackURL(); + // run the setup function for webhooks - webhooks.setupHooks(credentials); + webhooks.setupHooks(webhookUrl, credentials); // register secret token webhooks.setupToken(credentials); @@ -162,7 +190,7 @@ const createServer = () => { const fileName = body.payload.name; const destination = __dirname + "/file_share" + config.folderIDtoLocal[body.payload.parentFolderUrn]; await downloader.download(config.projectID, itemID, fileName, destination, credentials); - await deleter.delete(config.projectID, itemID, fileName, credentials); + // await deleter.delete(config.projectID, itemID, fileName, credentials); } }); @@ -197,16 +225,19 @@ const createServer = () => { const refresh = () => { config.authClient .refreshToken(credentials, config.scopes) - .then((creds: ForgeSDK.AuthToken) => { + .then(async (creds: ForgeSDK.AuthToken) => { credentials = creds; console.log( "\x1b[92mserver.js::refresh:", "\x1b[0mnew token generated from refresh token:" ); console.log(credentials); + + // check callback URL + let webhookUrl = await getWebhookCallbackURL(); // check on webhooks - webhooks.setupHooks(credentials); + webhooks.setupHooks(webhookUrl, credentials); // refresh localhook credentials localhook.setCredentials(credentials);