From b937f4893e34747b3082d4a635e07cb847884bb4 Mon Sep 17 00:00:00 2001 From: ifedapoolarewaju Date: Mon, 2 Dec 2019 16:10:05 +0100 Subject: [PATCH 1/3] companion: support new Instagram Graph API --- package-lock.json | 34 ++-- packages/@uppy/companion/package.json | 2 +- packages/@uppy/companion/src/companion.js | 6 +- .../src/server/controllers/send-token.js | 3 +- .../companion/src/server/provider/Provider.js | 64 +++++++ .../src/server/provider/drive/index.js | 5 +- .../src/server/provider/dropbox/index.js | 5 +- .../src/server/provider/facebook/index.js | 5 +- .../companion/src/server/provider/index.js | 90 +++------- .../provider/instagram/graph/adapter.js | 72 ++++++++ .../server/provider/instagram/graph/index.js | 156 ++++++++++++++++++ .../src/server/provider/instagram/index.js | 5 +- .../src/server/provider/onedrive/index.js | 5 +- .../@uppy/companion/src/standalone/helper.js | 3 +- .../test/__tests__/provider-manager.js | 41 ++++- packages/@uppy/companion/test/mockserver.js | 2 +- 16 files changed, 403 insertions(+), 95 deletions(-) create mode 100644 packages/@uppy/companion/src/server/provider/Provider.js create mode 100644 packages/@uppy/companion/src/server/provider/instagram/graph/adapter.js create mode 100644 packages/@uppy/companion/src/server/provider/instagram/graph/index.js diff --git a/package-lock.json b/package-lock.json index 8f164e3c1..c69df04d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6125,7 +6125,7 @@ "express-prom-bundle": "3.3.0", "express-request-id": "1.4.1", "express-session": "1.15.6", - "grant-express": "4.1.2", + "grant": "github:ifedapoolarewaju/grant#ba442905a89c5f2041b6a9101d4be8ae15c20458", "helmet": "3.8.2", "isobject": "3.0.1", "jsonwebtoken": "8.3.0", @@ -6224,6 +6224,14 @@ "utils-merge": "1.0.1" } }, + "grant-express": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/grant-express/-/grant-express-4.6.4.tgz", + "integrity": "sha512-7pvLC7EWU5f6Vl+kq1ZBtt+cNayzTonsgvpOGpBXxl2P1xIbvamQKKElGLwunCp5iVn5N6T5N6vFSxX9YdnTEw==", + "requires": { + "grant": "4.6.4" + } + }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", @@ -17425,24 +17433,14 @@ "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" }, "grant": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/grant/-/grant-4.1.2.tgz", - "integrity": "sha512-J+Cb0m8vDYU3tvcA47AbcD4KMioWeN6RDPxnPbcqpqAuHrn/J61YZZO4nx2B1qDQEhSahW3NwQCM1PZov4uMyw==", + "version": "github:ifedapoolarewaju/grant#ba442905a89c5f2041b6a9101d4be8ae15c20458", + "from": "github:ifedapoolarewaju/grant#ba442905a89c5f2041b6a9101d4be8ae15c20458", "requires": { - "deep-copy": "^1.4.2", - "qs": "^6.5.1", - "request-compose": "0.0.19", + "qs": "^6.7.0", + "request-compose": "^1.2.0", "request-oauth": "0.0.3" } }, - "grant-express": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/grant-express/-/grant-express-4.1.2.tgz", - "integrity": "sha512-q90pj9XM5tUNAVkTIy/N73vK9rc+SiW4J5CUG/z30yL29PM5Yzpt1kORBoqsAmygTSUH3L/ZupXg1Dng3SXM1g==", - "requires": { - "grant": "4.1.2" - } - }, "grapheme-breaker": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz", @@ -28087,9 +28085,9 @@ } }, "request-compose": { - "version": "0.0.19", - "resolved": "https://registry.npmjs.org/request-compose/-/request-compose-0.0.19.tgz", - "integrity": "sha512-BBMilZ4uReMzOCXvysw6l8nT5WwQDo/H8vaYNQ4BXPa7/0OJIaJskk4Ozzfpd2bmLb5ZQLpxJf/FMCeTX5QrkQ==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/request-compose/-/request-compose-1.2.1.tgz", + "integrity": "sha512-w4qjUH1N4OdMfnHVi4Z0oKvDZyu75rJlvnuKe40wVg+khnfdJLt0qf+LF8QjIiDqSOSYdbMZE6a0ixU58B3Jow==" }, "request-oauth": { "version": "0.0.3", diff --git a/packages/@uppy/companion/package.json b/packages/@uppy/companion/package.json index 8876061a0..e6bd3614a 100644 --- a/packages/@uppy/companion/package.json +++ b/packages/@uppy/companion/package.json @@ -43,7 +43,7 @@ "express-prom-bundle": "3.3.0", "express-request-id": "1.4.1", "express-session": "1.15.6", - "grant-express": "4.1.2", + "grant": "github:ifedapoolarewaju/grant#ba442905a89c5f2041b6a9101d4be8ae15c20458", "helmet": "3.8.2", "isobject": "3.0.1", "jsonwebtoken": "8.3.0", diff --git a/packages/@uppy/companion/src/companion.js b/packages/@uppy/companion/src/companion.js index 4a8a476f9..3c1ca672f 100644 --- a/packages/@uppy/companion/src/companion.js +++ b/packages/@uppy/companion/src/companion.js @@ -1,6 +1,6 @@ const express = require('express') // @ts-ignore -const Grant = require('grant-express') +const Grant = require('grant').express() const grantConfig = require('./config/grant')() const providerManager = require('./server/provider') const controllers = require('./server/controllers') @@ -19,7 +19,6 @@ const { STORAGE_PREFIX } = require('./server/Uploader') const middlewares = require('./server/middlewares') const { shortenToken } = require('./server/Uploader') -const providers = providerManager.getDefaultProviders() const defaultOptions = { server: { protocol: 'http', @@ -44,6 +43,7 @@ const defaultOptions = { */ module.exports.app = (options = {}) => { options = merge({}, defaultOptions, options) + const providers = providerManager.getDefaultProviders(options) providerManager.addProviderOptions(options, grantConfig) const customProviders = options.customProviders @@ -61,7 +61,7 @@ module.exports.app = (options = {}) => { app.use(cookieParser()) // server tokens are added to cookies app.use(interceptGrantErrorResponse) - app.use(new Grant(grantConfig)) + app.use(Grant(grantConfig)) app.use((req, res, next) => { res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE') res.header( diff --git a/packages/@uppy/companion/src/server/controllers/send-token.js b/packages/@uppy/companion/src/server/controllers/send-token.js index 4f072a83b..d5dde169e 100644 --- a/packages/@uppy/companion/src/server/controllers/send-token.js +++ b/packages/@uppy/companion/src/server/controllers/send-token.js @@ -19,7 +19,8 @@ module.exports = function sendToken (req, res, next) { // add the token to cookies for thumbnail/image requests tokenService.addToCookies(res, uppyAuthToken, req.companion.options, req.companion.provider.authProvider) - const state = (req.session.grant || {}).state + const dynamic = (req.session.grant || {}).dynamic || {} + const state = dynamic.state if (state) { const origin = oAuthState.getFromState(state, 'origin', req.companion.options.secret) const clientVersion = oAuthState.getFromState( diff --git a/packages/@uppy/companion/src/server/provider/Provider.js b/packages/@uppy/companion/src/server/provider/Provider.js new file mode 100644 index 000000000..e6974079e --- /dev/null +++ b/packages/@uppy/companion/src/server/provider/Provider.js @@ -0,0 +1,64 @@ +/** + * Provider interface defines the specifications of any provider implementation + */ +class Provider { + /** + * + * @param {object} options + */ + constructor (options) { + return this + } + + /** + * config to extend the grant config + */ + static getExtraConfig () { + return {} + } + + /** + * list the files and folders in the provider account + * @param {object} options + * @param {function} cb + */ + list (options, cb) { + throw new Error('method not implemented') + } + + /** + * download a certain file from the provider account + * @param {object} options + * @param {function} cb + */ + download (options, cb) { + throw new Error('method not implemented') + } + + /** + * return a thumbnail for a provider file + * @param {object} options + * @param {function} cb + */ + thumbnail (options, cb) { + throw new Error('method not implemented') + } + + /** + * get the size of a certain file in the provider account + * @param {object} options + * @param {function} cb + */ + size (options, cb) { + throw new Error('method not implemented') + } + + /** + * @returns {string} + */ + static get authProvider () { + return '' + } +} + +module.exports = Provider diff --git a/packages/@uppy/companion/src/server/provider/drive/index.js b/packages/@uppy/companion/src/server/provider/drive/index.js index c9421ec12..98e6d777d 100644 --- a/packages/@uppy/companion/src/server/provider/drive/index.js +++ b/packages/@uppy/companion/src/server/provider/drive/index.js @@ -1,3 +1,5 @@ +const Provider = require('../Provider') + const request = require('request') // @ts-ignore const purest = require('purest')({ request }) @@ -9,8 +11,9 @@ const DRIVE_FILES_FIELDS = `kind,nextPageToken,incompleteSearch,files(${DRIVE_FI // using wildcard to get all 'drive' fields because specifying fields seems no to work for the /drives endpoint const SHARED_DRIVE_FIELDS = '*' -class Drive { +class Drive extends Provider { constructor (options) { + super(options) this.authProvider = options.provider = Drive.authProvider options.alias = 'drive' options.version = 'v3' diff --git a/packages/@uppy/companion/src/server/provider/dropbox/index.js b/packages/@uppy/companion/src/server/provider/dropbox/index.js index 2193bb844..3fc117e77 100644 --- a/packages/@uppy/companion/src/server/provider/dropbox/index.js +++ b/packages/@uppy/companion/src/server/provider/dropbox/index.js @@ -1,3 +1,5 @@ +const Provider = require('../Provider') + const request = require('request') const purest = require('purest')({ request }) const logger = require('../../logger') @@ -17,8 +19,9 @@ function httpHeaderSafeJson (v) { ) } -class DropBox { +class DropBox extends Provider { constructor (options) { + super(options) this.authProvider = options.provider = DropBox.authProvider this.client = purest(options) } diff --git a/packages/@uppy/companion/src/server/provider/facebook/index.js b/packages/@uppy/companion/src/server/provider/facebook/index.js index d5226b25c..1c34fc445 100644 --- a/packages/@uppy/companion/src/server/provider/facebook/index.js +++ b/packages/@uppy/companion/src/server/provider/facebook/index.js @@ -1,3 +1,5 @@ +const Provider = require('../Provider') + const request = require('request') const purest = require('purest')({ request }) const utils = require('../../helpers/utils') @@ -5,8 +7,9 @@ const logger = require('../../logger') const adapter = require('./adapter') const AuthError = require('../error') -class Facebook { +class Facebook extends Provider { constructor (options) { + super(options) this.authProvider = options.provider = Facebook.authProvider this.client = purest(options) } diff --git a/packages/@uppy/companion/src/server/provider/index.js b/packages/@uppy/companion/src/server/provider/index.js index 895491341..3503457c0 100644 --- a/packages/@uppy/companion/src/server/provider/index.js +++ b/packages/@uppy/companion/src/server/provider/index.js @@ -6,62 +6,13 @@ const config = require('@purest/providers') const dropbox = require('./dropbox') const drive = require('./drive') const instagram = require('./instagram') +const instagramGraph = require('./instagram/graph') const facebook = require('./facebook') const onedrive = require('./onedrive') const { getURLBuilder } = require('../helpers/utils') const logger = require('../logger') - -/** - * Provider interface defines the specifications of any provider implementation - * - * @interface - */ -class Provider { - /** - * - * @param {object} options - */ - constructor (options) { - return this - } - - /** - * - * @param {object} options - * @param {function} cb - */ - list (options, cb) {} - - /** - * - * @param {object} options - * @param {function} cb - */ - download (options, cb) {} - - /** - * - * @param {object} options - * @param {function} cb - */ - thumbnail (options, cb) {} - - /** - * - * @param {object} options - * @param {function} cb - */ - size (options, cb) {} - - /** - * @returns {string} - */ - static get authProvider () { - return '' - } -} - -module.exports.ProviderInterface = Provider +// eslint-disable-next-line +const Provider = require('./Provider') /** * adds the desired provider module to the request object, @@ -90,10 +41,19 @@ module.exports.getProviderMiddleware = (providers) => { } /** + * @param {{server: object, providerOptions: object}} companionOptions * @return {Object.} */ -module.exports.getDefaultProviders = () => { - return { dropbox, drive, instagram, facebook, onedrive } +module.exports.getDefaultProviders = (companionOptions) => { + const { providerOptions } = companionOptions || { providerOptions: null } + const providers = { dropbox, drive, facebook, onedrive } + if (providerOptions && providerOptions.instagram && providerOptions.instagram.useGraphAPI) { + providers.instagram = instagramGraph + } else { + providers.instagram = instagram + } + + return providers } /** @@ -113,17 +73,17 @@ module.exports.addCustomProviders = (customProviders, providers, grantConfig) => /** * - * @param {{server: object, providerOptions: object}} options + * @param {{server: object, providerOptions: object}} companionOptions * @param {object} grantConfig */ -module.exports.addProviderOptions = (options, grantConfig) => { - const { server, providerOptions } = options +module.exports.addProviderOptions = (companionOptions, grantConfig) => { + const { server, providerOptions } = companionOptions if (!validOptions({ server })) { logger.warn('invalid provider options detected. Providers will not be loaded', 'provider.options.invalid') return } - grantConfig.server = { + grantConfig.defaults = { host: server.host, protocol: server.protocol, path: server.path @@ -136,13 +96,15 @@ module.exports.addProviderOptions = (options, grantConfig) => { // explicitly add providerOptions so users don't override other providerOptions. grantConfig[authProvider].key = providerOptions[authProvider].key grantConfig[authProvider].secret = providerOptions[authProvider].secret + const { provider, name } = authNameToProvider(authProvider, companionOptions) + Object.assign(grantConfig[authProvider], provider.getExtraConfig()) // override grant.js redirect uri with companion's custom redirect url if (oauthDomain) { - const providerName = authToProviderName(authProvider) + const providerName = name const redirectPath = `/${providerName}/redirect` const isExternal = !!server.implicitPath - const fullRedirectPath = getURLBuilder(options)(redirectPath, isExternal, true) + const fullRedirectPath = getURLBuilder(companionOptions)(redirectPath, isExternal, true) grantConfig[authProvider].redirect_uri = `${server.protocol}://${oauthDomain}${fullRedirectPath}` } @@ -161,14 +123,16 @@ module.exports.addProviderOptions = (options, grantConfig) => { /** * * @param {string} authProvider + * @param {{server: object, providerOptions: object}} options + * @return {{name: string, provider: typeof Provider}} */ -const authToProviderName = (authProvider) => { - const providers = exports.getDefaultProviders() +const authNameToProvider = (authProvider, options) => { + const providers = exports.getDefaultProviders(options) const providerNames = Object.keys(providers) for (const name of providerNames) { const provider = providers[name] if (provider.authProvider === authProvider) { - return name + return { name, provider } } } } diff --git a/packages/@uppy/companion/src/server/provider/instagram/graph/adapter.js b/packages/@uppy/companion/src/server/provider/instagram/graph/adapter.js new file mode 100644 index 000000000..fe1f4ff3a --- /dev/null +++ b/packages/@uppy/companion/src/server/provider/instagram/graph/adapter.js @@ -0,0 +1,72 @@ +const querystring = require('querystring') + +const MEDIA_TYPES = Object.freeze({ + video: 'VIDEO', + carousel: 'CAROUSEL_ALBUM', + image: 'IMAGE' +}) + +const isVideo = (item) => item.media_type === MEDIA_TYPES.video + +exports.isFolder = (_) => { + return false +} + +exports.getItemIcon = (item) => { + return isVideo(item) ? item.thumbnail_url : item.media_url +} + +exports.getItemSubList = (item) => { + const newItems = [] + item.data.forEach((subItem) => { + // exclude videos because of bug https://developers.facebook.com/support/bugs/801145630390846/ + // @todo remove this clause when bug is fixed + if (isVideo(subItem)) { + return + } + + if (subItem.media_type === MEDIA_TYPES.carousel) { + subItem.children.data.forEach((i) => { + // exclude videos because of bug https://developers.facebook.com/support/bugs/801145630390846/ + // @todo remove this clause when bug is fixed + if (isVideo(i)) { + return + } + + newItems.push(i) + }) + } else { + newItems.push(subItem) + } + }) + return newItems +} + +exports.getItemName = (item, index) => { + const ext = isVideo(item) ? 'mp4' : 'jpeg' + // adding index, so the name is unique + return `Instagram ${item.timestamp}${index}.${ext}` +} + +exports.getMimeType = (item) => { + return isVideo(item) ? 'video/mp4' : 'image/jpeg' +} + +exports.getItemId = (item) => item.id + +exports.getItemRequestPath = (item) => item.id + +exports.getItemModifiedDate = (item) => item.timestamp + +exports.getItemThumbnailUrl = (item) => exports.getItemIcon(item) + +exports.getNextPagePath = (data, currentQuery, currentPath) => { + if (!data.paging || !data.paging.cursors) { + return null + } + + const query = Object.assign({}, currentQuery, { + cursor: data.paging.cursors.after + }) + return `${currentPath || ''}?${querystring.stringify(query)}` +} diff --git a/packages/@uppy/companion/src/server/provider/instagram/graph/index.js b/packages/@uppy/companion/src/server/provider/instagram/graph/index.js new file mode 100644 index 000000000..3447e6c45 --- /dev/null +++ b/packages/@uppy/companion/src/server/provider/instagram/graph/index.js @@ -0,0 +1,156 @@ +const Provider = require('../../Provider') + +const request = require('request') +const purest = require('purest')({ request }) +const utils = require('../../../helpers/utils') +const logger = require('../../../logger') +const adapter = require('./adapter') +const AuthError = require('../../error') + +class Instagram extends Provider { + constructor (options) { + super(options) + this.authProvider = options.provider = Instagram.authProvider + this.client = purest(options) + } + + static getExtraConfig () { + return { + protocol: 'https', + credentials_fields: { key: 'app_id', secret: 'app_secret' }, + scope: ['user_profile', 'user_media'], + scope_delimiter: ',' + } + } + + static get authProvider () { + return 'instagram' + } + + list ({ directory, token, query = {} }, done) { + const qs = { + fields: 'id,media_type,thumbnail_url,media_url,timestamp,children{media_type,media_url,thumbnail_url,timestamp}' + } + + if (query.cursor) { + qs.after = query.cursor + } + + this.client + .get('https://graph.instagram.com/me/media') + .qs(qs) + .auth(token) + .request((err, resp, body) => { + if (err || resp.statusCode !== 200) { + err = this._error(err, resp) + logger.error(err, 'provider.instagram.list.error') + return done(err) + } else { + this._getUsername(token, (err, username) => { + err ? done(err) : done(null, this.adaptData(body, username, directory, query)) + }) + } + }) + } + + _getUsername (token, done) { + this.client + .get('https://graph.instagram.com/me') + .qs({ fields: 'username' }) + .auth(token) + .request((err, resp, body) => { + if (err || resp.statusCode !== 200) { + err = this._error(err, resp) + logger.error(err, 'provider.instagram.user.error') + return done(err) + } else { + done(null, body.username) + } + }) + } + + download ({ id, token }, onData) { + return this.client + .get(`https://graph.instagram.com/${id}`) + .qs({ fields: 'media_url' }) + .auth(token) + .request((err, resp, body) => { + if (err) return logger.error(err, 'provider.instagram.download.error') + request(body.media_url) + .on('data', onData) + .on('end', () => onData(null)) + .on('error', (err) => { + logger.error(err, 'provider.instagram.download.url.error') + }) + }) + } + + thumbnail (_, done) { + // not implementing this because a public thumbnail from instagram will be used instead + const err = new Error('call to thumbnail is not implemented') + logger.error(err, 'provider.instagram.thumbnail.error') + return done(err) + } + + size ({ id, token }, done) { + return this.client + .get(`https://graph.instagram.com/${id}`) + .qs({ fields: 'media_url' }) + .auth(token) + .request((err, resp, body) => { + if (err || resp.statusCode !== 200) { + err = this._error(err, resp) + logger.error(err, 'provider.instagram.size.error') + return done(err) + } + + utils.getURLMeta(body.media_url) + .then(({ size }) => done(null, size)) + .catch((err) => { + logger.error(err, 'provider.instagram.size.error') + done() + }) + }) + } + + logout (_, done) { + // access revoke is not supported by Instagram's API + done(null, { revoked: false, manual_revoke_url: 'https://www.instagram.com/accounts/manage_access/' }) + } + + adaptData (res, username, directory, currentQuery) { + const data = { username: username, items: [] } + const items = adapter.getItemSubList(res) + items.forEach((item, i) => { + data.items.push({ + isFolder: adapter.isFolder(item), + icon: adapter.getItemIcon(item), + name: adapter.getItemName(item, i), + mimeType: adapter.getMimeType(item), + id: adapter.getItemId(item), + thumbnail: adapter.getItemThumbnailUrl(item), + requestPath: adapter.getItemRequestPath(item), + modifiedDate: adapter.getItemModifiedDate(item) + }) + }) + + data.nextPagePath = adapter.getNextPagePath(res, currentQuery, directory) + return data + } + + _error (err, resp) { + if (resp) { + if (resp.body && resp.body.error.code === 190) { + // Invalid OAuth 2.0 Access Token + return new AuthError() + } + + const msg = resp.body && resp.body.error ? resp.body.error.message : '' + return new Error(`request to ${this.authProvider} returned status: ${resp.statusCode}, message: ${msg}`) + } + + return err + } +} + +module.exports = Instagram diff --git a/packages/@uppy/companion/src/server/provider/instagram/index.js b/packages/@uppy/companion/src/server/provider/instagram/index.js index a5865e344..f155fbd5a 100644 --- a/packages/@uppy/companion/src/server/provider/instagram/index.js +++ b/packages/@uppy/companion/src/server/provider/instagram/index.js @@ -1,3 +1,5 @@ +const Provider = require('../Provider') + const request = require('request') const purest = require('purest')({ request }) const utils = require('../../helpers/utils') @@ -5,8 +7,9 @@ const logger = require('../../logger') const adapter = require('./adapter') const AuthError = require('../error') -class Instagram { +class Instagram extends Provider { constructor (options) { + super(options) this.authProvider = options.provider = Instagram.authProvider this.client = purest(options) } diff --git a/packages/@uppy/companion/src/server/provider/onedrive/index.js b/packages/@uppy/companion/src/server/provider/onedrive/index.js index 4bfa26540..2bd8402b9 100644 --- a/packages/@uppy/companion/src/server/provider/onedrive/index.js +++ b/packages/@uppy/companion/src/server/provider/onedrive/index.js @@ -1,11 +1,14 @@ +const Provider = require('../Provider') + const request = require('request') const purest = require('purest')({ request }) const logger = require('../../logger') const adapter = require('./adapter') const AuthError = require('../error') -class OneDrive { +class OneDrive extends Provider { constructor (options) { + super(options) this.authProvider = options.provider = OneDrive.authProvider this.client = purest(options) } diff --git a/packages/@uppy/companion/src/standalone/helper.js b/packages/@uppy/companion/src/standalone/helper.js index 64d961e7d..f7abbe64a 100644 --- a/packages/@uppy/companion/src/standalone/helper.js +++ b/packages/@uppy/companion/src/standalone/helper.js @@ -39,7 +39,8 @@ const getConfigFromEnv = () => { }, instagram: { key: process.env.COMPANION_INSTAGRAM_KEY, - secret: getSecret('COMPANION_INSTAGRAM_SECRET') + secret: getSecret('COMPANION_INSTAGRAM_SECRET'), + useGraphAPI: !!process.env.COMPANION_INSTAGRAM_USE_GRAPH_API }, facebook: { key: process.env.COMPANION_FACEBOOK_KEY, diff --git a/packages/@uppy/companion/test/__tests__/provider-manager.js b/packages/@uppy/companion/test/__tests__/provider-manager.js index 7a12e9a7c..2554442e5 100644 --- a/packages/@uppy/companion/test/__tests__/provider-manager.js +++ b/packages/@uppy/companion/test/__tests__/provider-manager.js @@ -1,13 +1,14 @@ /* global jest:false, test:false, expect:false, describe:false, beforeEach:false */ const providerManager = require('../../src/server/provider') +const { getCompanionOptions } = require('../../src/standalone/helper') let grantConfig let companionOptions describe('Test Provider options', () => { beforeEach(() => { grantConfig = require('../../src/config/grant')() - companionOptions = require('../../src/standalone/helper').getCompanionOptions() + companionOptions = getCompanionOptions() }) test('adds provider options', () => { @@ -22,12 +23,48 @@ describe('Test Provider options', () => { expect(grantConfig.instagram.secret).toBe('instagram_secret') }) + test('adds extra provider config', () => { + process.env.COMPANION_INSTAGRAM_USE_GRAPH_API = 'truthy value' + providerManager.addProviderOptions(getCompanionOptions(), grantConfig) + expect(grantConfig.instagram).toEqual({ + transport: 'session', + callback: '/instagram/callback', + key: 'instagram_key', + secret: 'instagram_secret', + protocol: 'https', + credentials_fields: { key: 'app_id', secret: 'app_secret' }, + scope: ['user_profile', 'user_media'], + scope_delimiter: ',' + }) + + expect(grantConfig.dropbox).toEqual({ + key: 'dropbox_key', + secret: 'dropbox_secret', + transport: 'session', + authorize_url: 'https://www.dropbox.com/oauth2/authorize', + access_url: 'https://api.dropbox.com/oauth2/token', + callback: '/dropbox/callback' + }) + + expect(grantConfig.google).toEqual({ + key: 'google_key', + secret: 'google_secret', + transport: 'session', + scope: [ + 'https://www.googleapis.com/auth/drive.readonly' + ], + callback: '/drive/callback' + }) + + process.env.COMPANION_INSTAGRAM_USE_GRAPH_API = '' + }) + test('adds provider options for secret files', () => { process.env.COMPANION_DROPBOX_SECRET_FILE = process.env.PWD + '/test/resources/dropbox_secret_file' process.env.COMPANION_GOOGLE_SECRET_FILE = process.env.PWD + '/test/resources/google_secret_file' process.env.COMPANION_INSTAGRAM_SECRET_FILE = process.env.PWD + '/test/resources/instagram_secret_file' - companionOptions = require('../../src/standalone/helper').getCompanionOptions() + companionOptions = getCompanionOptions() providerManager.addProviderOptions(companionOptions, grantConfig) diff --git a/packages/@uppy/companion/test/mockserver.js b/packages/@uppy/companion/test/mockserver.js index 6bb746479..7e2460943 100644 --- a/packages/@uppy/companion/test/mockserver.js +++ b/packages/@uppy/companion/test/mockserver.js @@ -12,7 +12,7 @@ authServer.all('*/callback', (req, res, next) => { next() }) authServer.all('/drive/send-token', (req, res, next) => { - req.session.grant = { state: req.query.state || 'non-empty-value' } + req.session.grant = { dynamic: { state: req.query.state || 'non-empty-value' } } next() }) From c18706c8ce5506d13ff0dde6e02ff38aa5131ce7 Mon Sep 17 00:00:00 2001 From: ifedapoolarewaju Date: Wed, 4 Dec 2019 17:43:21 +0100 Subject: [PATCH 2/3] companion: update docs + fix test --- package-lock.json | 6 +-- packages/@uppy/companion/package.json | 2 +- .../companion/src/server/provider/Provider.js | 46 +++++++++---------- website/src/docs/companion.md | 6 ++- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index c69df04d9..60b4ef9d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6125,7 +6125,7 @@ "express-prom-bundle": "3.3.0", "express-request-id": "1.4.1", "express-session": "1.15.6", - "grant": "github:ifedapoolarewaju/grant#ba442905a89c5f2041b6a9101d4be8ae15c20458", + "grant": "github:ifedapoolarewaju/grant#a2696b67bf90de9adc0bd06043c6f5b724a64674", "helmet": "3.8.2", "isobject": "3.0.1", "jsonwebtoken": "8.3.0", @@ -17433,8 +17433,8 @@ "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" }, "grant": { - "version": "github:ifedapoolarewaju/grant#ba442905a89c5f2041b6a9101d4be8ae15c20458", - "from": "github:ifedapoolarewaju/grant#ba442905a89c5f2041b6a9101d4be8ae15c20458", + "version": "github:ifedapoolarewaju/grant#a2696b67bf90de9adc0bd06043c6f5b724a64674", + "from": "github:ifedapoolarewaju/grant#a2696b67bf90de9adc0bd06043c6f5b724a64674", "requires": { "qs": "^6.7.0", "request-compose": "^1.2.0", diff --git a/packages/@uppy/companion/package.json b/packages/@uppy/companion/package.json index e6bd3614a..a144ab8b1 100644 --- a/packages/@uppy/companion/package.json +++ b/packages/@uppy/companion/package.json @@ -43,7 +43,7 @@ "express-prom-bundle": "3.3.0", "express-request-id": "1.4.1", "express-session": "1.15.6", - "grant": "github:ifedapoolarewaju/grant#ba442905a89c5f2041b6a9101d4be8ae15c20458", + "grant": "github:ifedapoolarewaju/grant#a2696b67bf90de9adc0bd06043c6f5b724a64674", "helmet": "3.8.2", "isobject": "3.0.1", "jsonwebtoken": "8.3.0", diff --git a/packages/@uppy/companion/src/server/provider/Provider.js b/packages/@uppy/companion/src/server/provider/Provider.js index e6974079e..0a935e966 100644 --- a/packages/@uppy/companion/src/server/provider/Provider.js +++ b/packages/@uppy/companion/src/server/provider/Provider.js @@ -3,59 +3,59 @@ */ class Provider { /** - * - * @param {object} options - */ + * + * @param {object} options + */ constructor (options) { return this } /** - * config to extend the grant config - */ + * config to extend the grant config + */ static getExtraConfig () { return {} } /** - * list the files and folders in the provider account - * @param {object} options - * @param {function} cb - */ + * list the files and folders in the provider account + * @param {object} options + * @param {function} cb + */ list (options, cb) { throw new Error('method not implemented') } /** - * download a certain file from the provider account - * @param {object} options - * @param {function} cb - */ + * download a certain file from the provider account + * @param {object} options + * @param {function} cb + */ download (options, cb) { throw new Error('method not implemented') } /** - * return a thumbnail for a provider file - * @param {object} options - * @param {function} cb - */ + * return a thumbnail for a provider file + * @param {object} options + * @param {function} cb + */ thumbnail (options, cb) { throw new Error('method not implemented') } /** - * get the size of a certain file in the provider account - * @param {object} options - * @param {function} cb - */ + * get the size of a certain file in the provider account + * @param {object} options + * @param {function} cb + */ size (options, cb) { throw new Error('method not implemented') } /** - * @returns {string} - */ + * @returns {string} + */ static get authProvider () { return '' } diff --git a/website/src/docs/companion.md b/website/src/docs/companion.md index 3544b59a9..8fb821e99 100644 --- a/website/src/docs/companion.md +++ b/website/src/docs/companion.md @@ -177,6 +177,8 @@ export COMPANION_INSTAGRAM_KEY="YOUR INSTAGRAM KEY" export COMPANION_INSTAGRAM_SECRET="YOUR INSTAGRAM SECRET" # specifying a secret file will override a directly set secret export COMPANION_INSTAGRAM_SECRET_FILE="PATH/TO/INSTAGRAM/SECRET/FILE" +# set this value only if you are using the new Instagram Graph API https://developers.facebook.com/docs/instagram-basic-display-api +export COMPANION_INSTAGRAM_USE_GRAPH_API="true" # to enable Facebook export COMPANION_FACEBOOK_KEY="YOUR FACEBOOK KEY" @@ -230,7 +232,9 @@ See [env.example.sh](https://github.com/transloadit/uppy/blob/master/env.example }, instagram: { key: "***", - secret: "***" + secret: "***", + // set this to true only if you are using the new Instagram Graph API https://developers.facebook.com/docs/instagram-basic-display-api + useGraphAPI: false // default: false }, facebook: { key: "***", From b9aab9dea922e0a799fef86c5fc4153b4da352fd Mon Sep 17 00:00:00 2001 From: ifedapoolarewaju Date: Thu, 12 Dec 2019 00:54:02 +0100 Subject: [PATCH 3/3] companion: use updated grant js version for instagram graph --- package-lock.json | 178 +++++++----------- packages/@uppy/companion/package.json | 2 +- .../companion/src/server/provider/index.js | 4 +- .../server/provider/instagram/graph/index.js | 4 +- .../@uppy/companion/src/standalone/helper.js | 3 +- .../test/__tests__/provider-manager.js | 10 +- website/src/docs/companion.md | 6 +- 7 files changed, 74 insertions(+), 133 deletions(-) diff --git a/package-lock.json b/package-lock.json index 60b4ef9d8..a9b569fa0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5910,8 +5910,7 @@ "dependencies": { "es6-promise": { "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "bundled": true } } }, @@ -6014,8 +6013,7 @@ "dependencies": { "react": { "version": "16.5.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.5.0.tgz", - "integrity": "sha512-nw/yB/L51kA9PsAy17T1JrzzGRk+BlFCJwFF7p+pwVxgqwPjYNeZEkkH7LXn9dmflolrYMXLWMTkQ77suKPTNQ==", + "bundled": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -6059,8 +6057,7 @@ "dependencies": { "drag-drop": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/drag-drop/-/drag-drop-4.2.0.tgz", - "integrity": "sha512-RA8jXrxOlOFzkM5+tapHeavt0PIlh4FReYx4Ct9ECBRMxixPKUehRs4OQSruAPhQScClt1JaZ3M882FQdcZWaw==", + "bundled": true, "requires": { "blob-to-buffer": "^1.0.2", "flatten": "^1.0.2", @@ -6125,7 +6122,7 @@ "express-prom-bundle": "3.3.0", "express-request-id": "1.4.1", "express-session": "1.15.6", - "grant": "github:ifedapoolarewaju/grant#a2696b67bf90de9adc0bd06043c6f5b724a64674", + "grant": "4.6.5", "helmet": "3.8.2", "isobject": "3.0.1", "jsonwebtoken": "8.3.0", @@ -6149,13 +6146,11 @@ "dependencies": { "atob": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.0.tgz", - "integrity": "sha512-SuiKH8vbsOyCALjA/+EINmt/Kdl+TQPrtFgW7XZZcwtryFu9e5kQoX3bjCW6mIvGH1fbeAZZuvwGR5IlBRznGw==" + "bundled": true }, "body-parser": { "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "bundled": true, "requires": { "bytes": "3.0.0", "content-type": "~1.0.4", @@ -6171,23 +6166,19 @@ }, "buffer-from": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" + "bundled": true }, "bytes": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "bundled": true }, "connect-redis": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-4.0.3.tgz", - "integrity": "sha512-Php0P0ShNfilW6f2d/2v7Q0VAiFeBYsg0bIgu8ST3x26CcQ1JtzV6vxPLUwK0uiq10hQSMR+HzSNhWbcvx6nLg==" + "bundled": true }, "cookie-parser": { "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", - "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", + "bundled": true, "requires": { "cookie": "0.3.1", "cookie-signature": "1.0.6" @@ -6195,23 +6186,20 @@ }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "bundled": true, "requires": { "ms": "2.0.0" }, "dependencies": { "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "bundled": true } } }, "express-session": { "version": "1.15.6", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", - "integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==", + "bundled": true, "requires": { "cookie": "0.3.1", "cookie-signature": "1.0.6", @@ -6224,18 +6212,29 @@ "utils-merge": "1.0.1" } }, + "grant": { + "version": "4.6.5", + "bundled": true, + "requires": { + "qs": "^6.9.1", + "request-compose": "^1.2.1", + "request-oauth": "0.0.3" + }, + "dependencies": { + "qs": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz", + "integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==" + } + } + }, "grant-express": { "version": "4.6.4", - "resolved": "https://registry.npmjs.org/grant-express/-/grant-express-4.6.4.tgz", - "integrity": "sha512-7pvLC7EWU5f6Vl+kq1ZBtt+cNayzTonsgvpOGpBXxl2P1xIbvamQKKElGLwunCp5iVn5N6T5N6vFSxX9YdnTEw==", - "requires": { - "grant": "4.6.4" - } + "bundled": true }, "http-errors": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "bundled": true, "requires": { "depd": "~1.1.2", "inherits": "2.0.3", @@ -6245,28 +6244,23 @@ }, "iconv-lite": { "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + "bundled": true }, "lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "bundled": true }, "ms": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "bundled": true }, "qs": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + "bundled": true }, "raw-body": { "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "bundled": true, "requires": { "bytes": "3.0.0", "http-errors": "1.6.2", @@ -6276,13 +6270,11 @@ "dependencies": { "depd": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + "bundled": true }, "http-errors": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "bundled": true, "requires": { "depd": "1.1.1", "inherits": "2.0.3", @@ -6292,15 +6284,13 @@ }, "setprototypeof": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + "bundled": true } } }, "request": { "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "bundled": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -6326,30 +6316,25 @@ "dependencies": { "qs": { "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "bundled": true }, "uuid": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + "bundled": true } } }, "semver": { "version": "6.1.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz", - "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==" + "bundled": true }, "setprototypeof": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + "bundled": true }, "tough-cookie": { "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "bundled": true, "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" @@ -6357,8 +6342,7 @@ }, "tus-js-client": { "version": "1.8.0-2", - "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-1.8.0-2.tgz", - "integrity": "sha512-8v/q4s9biAV1A1hZf2mtnvRlh7AXpXbozrX5bZgjRmhgY9TLlmfFVieamrOjN1DI9RPze9mSh3e6BQRRDIDsiA==", + "bundled": true, "requires": { "buffer-from": "^0.1.1", "combine-errors": "^3.0.3", @@ -6371,18 +6355,15 @@ }, "ultron": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + "bundled": true }, "uuid": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.2.tgz", - "integrity": "sha1-SL1WmPBnfjx5AaHEbvFbFkN5RyY=" + "bundled": true }, "ws": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.1.tgz", - "integrity": "sha512-8A/uRMnQy8KCQsmep1m7Bk+z/+LIkeF7w+TDMLtX1iZm5Hq9HsUDmgFGaW1ACW5Cj0b2Qo7wCvRhYN2ErUVp/A==", + "bundled": true, "requires": { "async-limiter": "~1.0.0", "safe-buffer": "~5.1.0", @@ -6614,13 +6595,11 @@ "dependencies": { "buffer-from": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", - "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" + "bundled": true }, "tus-js-client": { "version": "1.8.0-2", - "resolved": "https://registry.npmjs.org/tus-js-client/-/tus-js-client-1.8.0-2.tgz", - "integrity": "sha512-8v/q4s9biAV1A1hZf2mtnvRlh7AXpXbozrX5bZgjRmhgY9TLlmfFVieamrOjN1DI9RPze9mSh3e6BQRRDIDsiA==", + "bundled": true, "requires": { "buffer-from": "^0.1.1", "combine-errors": "^3.0.3", @@ -14940,7 +14919,7 @@ "qs": "^6.5.0", "react-native-branch": "2.2.5", "react-native-gesture-handler": "~1.0.14", - "react-native-maps": "github:expo/react-native-maps#v0.22.1-exp.0", + "react-native-maps": "github:expo/react-native-maps#e6f98ff7272e5d0a7fe974a41f28593af2d77bb2", "react-native-reanimated": "1.0.0-alpha.11", "react-native-screens": "1.0.0-alpha.22", "react-native-svg": "8.0.10", @@ -16159,8 +16138,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -16178,13 +16156,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -16197,18 +16173,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -16311,8 +16284,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -16322,7 +16294,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -16335,20 +16306,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -16365,7 +16333,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -16438,8 +16405,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -16449,7 +16415,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -16525,8 +16490,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -16556,7 +16520,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -16574,7 +16537,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -16613,13 +16575,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } }, @@ -17432,15 +17392,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" }, - "grant": { - "version": "github:ifedapoolarewaju/grant#a2696b67bf90de9adc0bd06043c6f5b724a64674", - "from": "github:ifedapoolarewaju/grant#a2696b67bf90de9adc0bd06043c6f5b724a64674", - "requires": { - "qs": "^6.7.0", - "request-compose": "^1.2.0", - "request-oauth": "0.0.3" - } - }, "grapheme-breaker": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz", @@ -32085,8 +32036,7 @@ "dependencies": { "drag-drop": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/drag-drop/-/drag-drop-4.2.0.tgz", - "integrity": "sha512-RA8jXrxOlOFzkM5+tapHeavt0PIlh4FReYx4Ct9ECBRMxixPKUehRs4OQSruAPhQScClt1JaZ3M882FQdcZWaw==", + "bundled": true, "requires": { "blob-to-buffer": "^1.0.2", "flatten": "^1.0.2", diff --git a/packages/@uppy/companion/package.json b/packages/@uppy/companion/package.json index a144ab8b1..5de774c47 100644 --- a/packages/@uppy/companion/package.json +++ b/packages/@uppy/companion/package.json @@ -43,7 +43,7 @@ "express-prom-bundle": "3.3.0", "express-request-id": "1.4.1", "express-session": "1.15.6", - "grant": "github:ifedapoolarewaju/grant#a2696b67bf90de9adc0bd06043c6f5b724a64674", + "grant": "4.6.5", "helmet": "3.8.2", "isobject": "3.0.1", "jsonwebtoken": "8.3.0", diff --git a/packages/@uppy/companion/src/server/provider/index.js b/packages/@uppy/companion/src/server/provider/index.js index 3503457c0..8dc742c3c 100644 --- a/packages/@uppy/companion/src/server/provider/index.js +++ b/packages/@uppy/companion/src/server/provider/index.js @@ -47,7 +47,9 @@ module.exports.getProviderMiddleware = (providers) => { module.exports.getDefaultProviders = (companionOptions) => { const { providerOptions } = companionOptions || { providerOptions: null } const providers = { dropbox, drive, facebook, onedrive } - if (providerOptions && providerOptions.instagram && providerOptions.instagram.useGraphAPI) { + // Instagram's Graph API key is just numbers, while the old API key is hex + const usesGraphAPI = () => /^\d+$/.test(providerOptions.instagram.key) + if (providerOptions && providerOptions.instagram && usesGraphAPI()) { providers.instagram = instagramGraph } else { providers.instagram = instagram diff --git a/packages/@uppy/companion/src/server/provider/instagram/graph/index.js b/packages/@uppy/companion/src/server/provider/instagram/graph/index.js index 3447e6c45..1bfe2734c 100644 --- a/packages/@uppy/companion/src/server/provider/instagram/graph/index.js +++ b/packages/@uppy/companion/src/server/provider/instagram/graph/index.js @@ -17,9 +17,7 @@ class Instagram extends Provider { static getExtraConfig () { return { protocol: 'https', - credentials_fields: { key: 'app_id', secret: 'app_secret' }, - scope: ['user_profile', 'user_media'], - scope_delimiter: ',' + scope: ['user_profile', 'user_media'] } } diff --git a/packages/@uppy/companion/src/standalone/helper.js b/packages/@uppy/companion/src/standalone/helper.js index f7abbe64a..64d961e7d 100644 --- a/packages/@uppy/companion/src/standalone/helper.js +++ b/packages/@uppy/companion/src/standalone/helper.js @@ -39,8 +39,7 @@ const getConfigFromEnv = () => { }, instagram: { key: process.env.COMPANION_INSTAGRAM_KEY, - secret: getSecret('COMPANION_INSTAGRAM_SECRET'), - useGraphAPI: !!process.env.COMPANION_INSTAGRAM_USE_GRAPH_API + secret: getSecret('COMPANION_INSTAGRAM_SECRET') }, facebook: { key: process.env.COMPANION_FACEBOOK_KEY, diff --git a/packages/@uppy/companion/test/__tests__/provider-manager.js b/packages/@uppy/companion/test/__tests__/provider-manager.js index 2554442e5..3a0d1c7f3 100644 --- a/packages/@uppy/companion/test/__tests__/provider-manager.js +++ b/packages/@uppy/companion/test/__tests__/provider-manager.js @@ -24,17 +24,15 @@ describe('Test Provider options', () => { }) test('adds extra provider config', () => { - process.env.COMPANION_INSTAGRAM_USE_GRAPH_API = 'truthy value' + process.env.COMPANION_INSTAGRAM_KEY = '123456' providerManager.addProviderOptions(getCompanionOptions(), grantConfig) expect(grantConfig.instagram).toEqual({ transport: 'session', callback: '/instagram/callback', - key: 'instagram_key', + key: '123456', secret: 'instagram_secret', protocol: 'https', - credentials_fields: { key: 'app_id', secret: 'app_secret' }, - scope: ['user_profile', 'user_media'], - scope_delimiter: ',' + scope: ['user_profile', 'user_media'] }) expect(grantConfig.dropbox).toEqual({ @@ -55,8 +53,6 @@ describe('Test Provider options', () => { ], callback: '/drive/callback' }) - - process.env.COMPANION_INSTAGRAM_USE_GRAPH_API = '' }) test('adds provider options for secret files', () => { diff --git a/website/src/docs/companion.md b/website/src/docs/companion.md index 8fb821e99..3544b59a9 100644 --- a/website/src/docs/companion.md +++ b/website/src/docs/companion.md @@ -177,8 +177,6 @@ export COMPANION_INSTAGRAM_KEY="YOUR INSTAGRAM KEY" export COMPANION_INSTAGRAM_SECRET="YOUR INSTAGRAM SECRET" # specifying a secret file will override a directly set secret export COMPANION_INSTAGRAM_SECRET_FILE="PATH/TO/INSTAGRAM/SECRET/FILE" -# set this value only if you are using the new Instagram Graph API https://developers.facebook.com/docs/instagram-basic-display-api -export COMPANION_INSTAGRAM_USE_GRAPH_API="true" # to enable Facebook export COMPANION_FACEBOOK_KEY="YOUR FACEBOOK KEY" @@ -232,9 +230,7 @@ See [env.example.sh](https://github.com/transloadit/uppy/blob/master/env.example }, instagram: { key: "***", - secret: "***", - // set this to true only if you are using the new Instagram Graph API https://developers.facebook.com/docs/instagram-basic-display-api - useGraphAPI: false // default: false + secret: "***" }, facebook: { key: "***",