From 2cecd1795e73454a3de41d86a3dd022da76d4889 Mon Sep 17 00:00:00 2001 From: pan261 Date: Thu, 4 Nov 2021 16:33:50 -0400 Subject: [PATCH] updated server to use forge api modules --- package.json | 5 +- puppeteer.js | 55 --------------------- server.js | 132 ++++++++++++++++++++++++++------------------------- test.js | 19 ++++++++ 4 files changed, 88 insertions(+), 123 deletions(-) delete mode 100644 puppeteer.js create mode 100644 test.js diff --git a/package.json b/package.json index f4a1d4f..4056bb4 100644 --- a/package.json +++ b/package.json @@ -15,12 +15,9 @@ "license": "ISC", "dependencies": { "axios": "^0.24.0", - "body-parser": "^1.19.0", "cookie-session": "^1.4.0", "dotenv": "^10.0.0", "express": "^4.17.1", - "forge-apis": "^0.8.6", - "puppeteer": "^10.4.0", - "querystring": "^0.2.1" + "forge-apis": "^0.8.6" } } diff --git a/puppeteer.js b/puppeteer.js deleted file mode 100644 index fd5f76a..0000000 --- a/puppeteer.js +++ /dev/null @@ -1,55 +0,0 @@ -const puppeteer = require('puppeteer'); -require('dotenv').config(); - -/* - Resources used: - https://pptr.dev/#?product=Puppeteer&version=v10.4.0&show=api-pageclickselector-options - https://help.apify.com/en/articles/1668473-submit-form-with-file-attachment-using-puppeteer - https://stackoverflow.com/questions/67407104/error-while-loading-shared-libraries-libgbm-so-1-cannot-open-shared-object-fil -*/ - -/* - Opens up a headless browser to get 3-Legged Token from local express server. - Must have AUTODESK_EMAIL and AUTODESK_PASSWORD in .env file in this directory - Must also have the server running on port 3000 - - Usage: `node puppeteer.js`: should return the page contents of the callback url from Forge Authentication - Includes the Auth token. -*/ - -(async () => { - if (process.env.AUTODESK_EMAIL == null || process.env.AUTODESK_PASSWORD == null) { - console.error('Missing AUTODESK_EMAIL or AUTODESK_PASSWORD env. variables.'); - return; - } - - const browser = await puppeteer.launch({ - headless: true, - args: ['--no-sandbox'] - }); - const page = await browser.newPage(); - await page.goto('http://localhost:3000/auth'); - - await page.waitForSelector('input[name=UserName]'); - await page.type('input[name=UserName]', process.env.AUTODESK_EMAIL); - - await Promise.all([ - page.waitForNavigation(), - page.click('button[id=verify_user_btn]'), - ]); - - await page.waitForSelector('input[name=Password]'); - await page.type('input[name=Password]', process.env.AUTODESK_PASSWORD); - await Promise.all([ - page.waitForNavigation(), - page.click('button[id=btnSubmit]'), - ]); - - await Promise.all([ - page.waitForNavigation(), - page.click('a[id=allow_btn]'), - ]); - - console.log(await page.content()) - await browser.close(); -})(); \ No newline at end of file diff --git a/server.js b/server.js index ebb7a12..f46f6d1 100644 --- a/server.js +++ b/server.js @@ -1,12 +1,9 @@ const path = require('path'); const express = require('express'); const cookieSession = require('cookie-session'); -const querystring = require('querystring'); -const axios = require('axios'); -const bodyParser = require('body-parser'); require('dotenv').config(); -const PORT = process.env.PORT || 3000; +const ForgeSDK = require('forge-apis'); /* Resources used: @@ -20,69 +17,76 @@ const PORT = process.env.PORT || 3000; FORGE_CALLBACK_URL (should be 'http://localhost:3000/callback/') should be the same in the .env and in the Forge API project console. - Usage: node server.js or npm start + Usage: node test.js or npm start Navigate to http://localhost:3000/auth/ to get started Browser should then go through the Autodesk Auth screen and display Auth token. */ -if (process.env.FORGE_CLIENT_ID == null || process.env.FORGE_CLIENT_SECRET == null) { - console.error('Missing FORGE_CLIENT_ID or FORGE_CLIENT_SECRET env. variables.'); - return; + +/* + Function to start the server + TODO: return both the oAuth2ThreeLegged and credentials objects, these will be needed for other API wrappers +*/ +function createServer() { + const app = express(); + const PORT = process.env.PORT || 3000; + const scopes = ['bucket:create', 'bucket:read', 'data:read', 'data:create', 'data:write']; + const oAuth2ThreeLegged = new ForgeSDK.AuthClientThreeLegged( + process.env.FORGE_CLIENT_ID, + process.env.FORGE_CLIENT_SECRET, + process.env.FORGE_CALLBACK_URL, + scopes, + true + ); + + if (process.env.FORGE_CLIENT_ID == null || process.env.FORGE_CLIENT_SECRET == null) { + console.error('Missing FORGE_CLIENT_ID or FORGE_CLIENT_SECRET env. variables.'); + return; + } + + app.use(express.static(path.join(__dirname, 'public'))); + app.use(cookieSession({ + name: 'forge_session', + keys: ['forge_secure_key'], + maxAge: 14 * 24 * 60 * 60 * 1000 // 14 days, same as refresh token + })); + + // Endpoint to begin authentication process + app.get('/auth', function (req, res) { + res.redirect(oAuth2ThreeLegged.generateAuthUrl()); + }); + + // Endpoint Forge redirects to after consent screen + app.get('/callback', function (req, res) { + oAuth2ThreeLegged.getToken(req.query.code).then(function (credentials) { + console.log(credentials) + res.send('Generated token: ' + credentials.access_token); + }, function(err){ + console.error(err); + res.send('Failed to authenticate'); + }); + }); + + app.use((err, req, res, next) => { + console.error(err); + res.status(err.statusCode).json(err); + }); + + const server = app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); }); + + return server; } -const scopes = ['bucket:create', 'bucket:read', 'data:read', 'data:create', 'data:write']; - -let app = express(); -app.use(express.static(path.join(__dirname, 'public'))); -app.use(cookieSession({ - name: 'forge_session', - keys: ['forge_secure_key'], - maxAge: 14 * 24 * 60 * 60 * 1000 // 14 days, same as refresh token -})); - -app.get('/auth', function (req, res) { - var redirect_uri = 'https://developer.api.autodesk.com/authentication/v1/authorize?' - + 'response_type=code' - + '&client_id=' + process.env.FORGE_CLIENT_ID - + '&redirect_uri=' + process.env.FORGE_CALLBACK_URL - + '&scope=' + scopes.join(' '); - console.log(redirect_uri); - res.redirect(redirect_uri); -}); - -app.get('/callback', function (req, res) { - axios({ - method: 'POST', - url: 'https://developer.api.autodesk.com/authentication/v1/gettoken', - headers: { - 'content-type': 'application/x-www-form-urlencoded', - }, - data: querystring.stringify({ - client_id: process.env.FORGE_CLIENT_ID, - client_secret: process.env.FORGE_CLIENT_SECRET, - grant_type: 'authorization_code', - code: req.query.code, - redirect_uri: process.env.FORGE_CALLBACK_URL - }) - }) - .then(function (response) { - // Success - access_token = response.data.access_token; - console.log(response); - res.send('

Authentication success! Here is your token:

' + access_token); - }) - .catch(function (error) { - // Failed - console.log(error); - res.send('Failed to authenticate'); - }); -}); - -app.use((err, req, res, next) => { - console.error(err); - res.status(err.statusCode).json(err); -}); - -app.use(bodyParser.json()); - -app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); }); \ No newline at end of file +/* + Function to shutdown the server +*/ +function shutdownServer(server) { + server.close(() => { + console.log('Closing connections'); + return; + }); +} + + +module.exports.create = createServer; +module.exports.shutdown = shutdownServer; \ No newline at end of file diff --git a/test.js b/test.js new file mode 100644 index 0000000..d7713de --- /dev/null +++ b/test.js @@ -0,0 +1,19 @@ +const authServer = require('./server'); + +/* + Look at this for fetching new auth tokens in a loop: + https://nodejs.org/en/docs/guides/timers-in-node/ +*/ + +function intervalFunc() { + console.log('Running every 15 sec'); +} + +(async () => { + let server = await authServer.create(); +})(); + +/* + Testing setInterval function, will likely need to use this for refreshing auth tokens +*/ +setInterval(intervalFunc, 15000); \ No newline at end of file