mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-24 10:47:44 +00:00
Merge pull request #1966 from transloadit/instagram-graph
companion: support new Instagram Graph API
This commit is contained in:
commit
cb75538fcd
15 changed files with 395 additions and 107 deletions
43
package-lock.json
generated
43
package-lock.json
generated
|
|
@ -6350,8 +6350,8 @@
|
|||
"express-interceptor": "1.2.0",
|
||||
"express-prom-bundle": "3.3.0",
|
||||
"express-request-id": "1.4.1",
|
||||
"express-session": "1.17.0",
|
||||
"grant-express": "4.1.2",
|
||||
"express-session": "1.15.6",
|
||||
"grant": "4.6.5",
|
||||
"helmet": "3.21.2",
|
||||
"isobject": "3.0.1",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
|
|
@ -6493,35 +6493,19 @@
|
|||
"integrity": "sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g=="
|
||||
},
|
||||
"express-session": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.0.tgz",
|
||||
"integrity": "sha512-t4oX2z7uoSqATbMfsxWMbNjAL0T5zpvcJCk3Z9wnPPN7ibddhnmDZXHfEcoBMG2ojKXZoCyPMc5FbtK+G7SoDg==",
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz",
|
||||
"integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==",
|
||||
"requires": {
|
||||
"cookie": "0.4.0",
|
||||
"cookie": "0.3.1",
|
||||
"cookie-signature": "1.0.6",
|
||||
"crc": "3.4.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~2.0.0",
|
||||
"on-headers": "~1.0.2",
|
||||
"parseurl": "~1.3.3",
|
||||
"safe-buffer": "5.2.0",
|
||||
"uid-safe": "~2.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"cookie": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
||||
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
|
||||
},
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||
}
|
||||
"depd": "~1.1.1",
|
||||
"on-headers": "~1.0.1",
|
||||
"parseurl": "~1.3.2",
|
||||
"uid-safe": "~2.1.5",
|
||||
"utils-merge": "1.0.1"
|
||||
}
|
||||
},
|
||||
"frameguard": {
|
||||
|
|
@ -12933,8 +12917,7 @@
|
|||
"crc": {
|
||||
"version": "3.4.4",
|
||||
"resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz",
|
||||
"integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=",
|
||||
"dev": true
|
||||
"integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms="
|
||||
},
|
||||
"crc32-stream": {
|
||||
"version": "3.0.1",
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@
|
|||
"express-interceptor": "1.2.0",
|
||||
"express-prom-bundle": "3.3.0",
|
||||
"express-request-id": "1.4.1",
|
||||
"express-session": "1.17.0",
|
||||
"grant-express": "4.1.2",
|
||||
"express-session": "1.15.6",
|
||||
"grant": "4.6.5",
|
||||
"helmet": "3.21.2",
|
||||
"isobject": "3.0.1",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
64
packages/@uppy/companion/src/server/provider/Provider.js
Normal file
64
packages/@uppy/companion/src/server/provider/Provider.js
Normal file
|
|
@ -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
|
||||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,21 @@ module.exports.getProviderMiddleware = (providers) => {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {{server: object, providerOptions: object}} companionOptions
|
||||
* @return {Object.<string, typeof Provider>}
|
||||
*/
|
||||
module.exports.getDefaultProviders = () => {
|
||||
return { dropbox, drive, instagram, facebook, onedrive }
|
||||
module.exports.getDefaultProviders = (companionOptions) => {
|
||||
const { providerOptions } = companionOptions || { providerOptions: null }
|
||||
const providers = { dropbox, drive, facebook, onedrive }
|
||||
// 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
|
||||
}
|
||||
|
||||
return providers
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -113,17 +75,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 +98,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 +125,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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)}`
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
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',
|
||||
scope: ['user_profile', 'user_media']
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,44 @@ describe('Test Provider options', () => {
|
|||
expect(grantConfig.instagram.secret).toBe('instagram_secret')
|
||||
})
|
||||
|
||||
test('adds extra provider config', () => {
|
||||
process.env.COMPANION_INSTAGRAM_KEY = '123456'
|
||||
providerManager.addProviderOptions(getCompanionOptions(), grantConfig)
|
||||
expect(grantConfig.instagram).toEqual({
|
||||
transport: 'session',
|
||||
callback: '/instagram/callback',
|
||||
key: '123456',
|
||||
secret: 'instagram_secret',
|
||||
protocol: 'https',
|
||||
scope: ['user_profile', 'user_media']
|
||||
})
|
||||
|
||||
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'
|
||||
})
|
||||
})
|
||||
|
||||
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue