diff --git a/docker-compose.yml b/docker-compose.yml index bc21142..87c052f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.8" services: - auth_server: + server: build: context: . dockerfile: Dockerfile @@ -9,6 +9,7 @@ services: volumes: - ./src/build:/ffs/ - /ffs/node_modules + - ./FileShare:/ffs/FileShare/ ports: - ${PORT}:${PORT} command: "node server.js" diff --git a/package.json b/package.json index cd51b70..ab72752 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "start": "docker-compose up", "test": "echo \"Error: no test specified\" && exit 1", "tsc": "tsc", - "docker:build": "tsc --build && docker-compose up --build --remove-orphans" + "build": "tsc --build && docker-compose up --build --remove-orphans" }, "repository": { "type": "git", diff --git a/src/config.ts b/src/config.ts index 34ace86..abac609 100644 --- a/src/config.ts +++ b/src/config.ts @@ -45,6 +45,14 @@ export const folderMap: any = { } }; +// dictionary for looking up local directory path based on folder ID +export const folderIDtoLocal: any = { + "urn:adsk.wipprod:fs.folder:co.IxiedfeBTOGg6NSIGQhXxQ" : "/Gantry", + "urn:adsk.wipprod:fs.folder:co.FDWCeyBGQX2rv8xSNWo5lg": "/Lathe", + "urn:adsk.wipprod:fs.folder:co.nEihcpHUSW-ZsVzU-__1iw": "/Mill", + "urn:adsk.wipprod:fs.folder:co.vJLXAKGbQQayeljr-nwztQ": "/Waterjet" +} + export const port = process.env.PORT; export const forgeClientId = process.env.FORGE_CLIENT_ID; export const forgeClientSecret = process.env.FORGE_CLIENT_SECRET; diff --git a/src/downloader.ts b/src/downloader.ts index 8a78bfa..3aeabaf 100644 --- a/src/downloader.ts +++ b/src/downloader.ts @@ -20,7 +20,7 @@ exports.download = async (projectID: string, itemID: string, fileName: string, d ObjectsApi.getObject('wip.dm.prod', storageLocation, {}, config.authClient, credentials) .then((res: any) => { - console.log(res) + console.log("downloaded file " + fileName + " to " + destination); fs.writeFile(`${destination}/${fileName}`, res.body) }) .catch((err: any) => { @@ -30,20 +30,20 @@ exports.download = async (projectID: string, itemID: string, fileName: string, d } const getStorageLocation = (projectID: string, itemID: string, credentials: any) => { - axios({ + return axios({ method: 'GET', url: `https://developer.api.autodesk.com/data/v1/projects/${projectID}/items/${itemID}`, headers: { Authorization: `Bearer ${credentials.access_token}` }, }).then((res: any) => { - return res.data.included; + return res.data.included[0]; }).then((data: any) => { var storageID = data.relationships.storage.data.id; storageID = storageID.substring(storageID.indexOf('/') + 1); return storageID; }).catch((err: any) => { - console.log(err) + console.log("unable to get storage location for " + itemID + ": " + err.response.status); }) } diff --git a/src/server.ts b/src/server.ts index 6401c0d..6973a50 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,11 +1,12 @@ import express = require('express'); -const webhooks = require('./webhooks'); import * as config from './config'; import fs = require('fs'); +const webhooks = require('./webhooks'); +const downloader = require('./downloader'); /** - * Kevin Pan | pan261@purdue.edu | Last Modified: 12/2/2021 + * Kevin Pan | pan261@purdue.edu | Last Modified: 1/24/2022 * * Authentication server used to perform 3-legged auth through browser. * @@ -111,8 +112,15 @@ const createServer = () => { }).on('data', (chunk: any) => { body.push(chunk); }).on('end', () => { - body = Buffer.concat(body).toString(); - console.log(body) + body = JSON.parse(Buffer.concat(body).toString()); + + if (credentials && body.hook.event === "dm.version.added") { + const itemID = body.payload.lineageUrn; + const fileName = body.payload.name; + const destination = __dirname + '/FileShare' + config.folderIDtoLocal[body.payload.parentFolderUrn]; + + downloader.download(config.projectID, itemID, fileName, destination, credentials); + } }) res.status(204).send(); }); diff --git a/src/webhooks.ts b/src/webhooks.ts index 738026d..c21f68a 100644 --- a/src/webhooks.ts +++ b/src/webhooks.ts @@ -2,7 +2,19 @@ const axios = require('axios'); import * as config from './config'; -// instead of using this file to constanly poll the api, it will setup and maintain the webhooks +/** + * Kevin Pan | pan261@purdue.edu | Last Modified: 1/24/2022 + * + * Functions to manage hook lifecycle + * setup() checks if hooks are valid and active, if not it will reactivated + * and/or recreate the specified hook. There is one hook for each of the + * following events: + * + * - 'dm.version.added' (file added) + * - 'dm.version.modified' (file modified) + * - dm.version.deleted (file deleted) + * + */ const FileShareID = "urn:adsk.wipprod:fs.folder:co.T0n0mYQeS16K0lq1VuuYVQ" @@ -63,7 +75,7 @@ const createHook = (event: string, credentials: any) => { Authorization: `Bearer ${credentials.access_token}` }, data: { - autoReactivateHook: true, + autoReactivateHook: "true", callbackUrl: config.hookCallbackURL, scope: { folder: FileShareID