Parcourir la source

Merge pull request #1286 from transloadit/provider-react-native

Make providers support react native
Ifedapo .A. Olarewaju il y a 6 ans
Parent
commit
9e79ec0d57

+ 12 - 4
packages/@uppy/companion-client/src/Provider.js

@@ -13,17 +13,22 @@ module.exports = class Provider extends RequestClient {
     this.id = this.provider
     this.id = this.provider
     this.authProvider = opts.authProvider || this.provider
     this.authProvider = opts.authProvider || this.provider
     this.name = this.opts.name || _getName(this.id)
     this.name = this.opts.name || _getName(this.id)
-    this.tokenKey = `companion-${this.id}-auth-token`
+    this.pluginId = this.opts.pluginId
+    this.tokenKey = `companion-${this.pluginId}-auth-token`
   }
   }
 
 
   get defaultHeaders () {
   get defaultHeaders () {
-    return Object.assign({}, super.defaultHeaders, {'uppy-auth-token': localStorage.getItem(this.tokenKey)})
+    return Object.assign({}, super.defaultHeaders, {'uppy-auth-token': this.getAuthToken()})
   }
   }
 
 
   // @todo(i.olarewaju) consider whether or not this method should be exposed
   // @todo(i.olarewaju) consider whether or not this method should be exposed
   setAuthToken (token) {
   setAuthToken (token) {
     // @todo(i.olarewaju) add fallback for OOM storage
     // @todo(i.olarewaju) add fallback for OOM storage
-    localStorage.setItem(this.tokenKey, token)
+    this.uppy.getPlugin(this.pluginId).storage.setItem(this.tokenKey, token)
+  }
+
+  getAuthToken () {
+    return this.uppy.getPlugin(this.pluginId).storage.getItem(this.tokenKey)
   }
   }
 
 
   checkAuth () {
   checkAuth () {
@@ -48,7 +53,7 @@ module.exports = class Provider extends RequestClient {
   logout (redirect = location.href) {
   logout (redirect = location.href) {
     return this.get(`${this.id}/logout?redirect=${redirect}`)
     return this.get(`${this.id}/logout?redirect=${redirect}`)
       .then((res) => {
       .then((res) => {
-        localStorage.removeItem(this.tokenKey)
+        this.storage.removeItem(this.tokenKey)
         return res
         return res
       })
       })
   }
   }
@@ -59,6 +64,7 @@ module.exports = class Provider extends RequestClient {
     if (defaultOpts) {
     if (defaultOpts) {
       plugin.opts = Object.assign({}, defaultOpts, opts)
       plugin.opts = Object.assign({}, defaultOpts, opts)
     }
     }
+
     if (opts.serverPattern) {
     if (opts.serverPattern) {
       const pattern = opts.serverPattern
       const pattern = opts.serverPattern
       // validate serverPattern param
       // validate serverPattern param
@@ -74,5 +80,7 @@ module.exports = class Provider extends RequestClient {
         plugin.opts.serverPattern = opts.serverUrl
         plugin.opts.serverPattern = opts.serverUrl
       }
       }
     }
     }
+
+    plugin.storage = plugin.opts.storage || localStorage
   }
   }
 }
 }

+ 1 - 29
packages/@uppy/companion/src/server/controllers/callback.js

@@ -1,11 +1,7 @@
 /**
 /**
  * oAuth callback.  Encrypts the access token and sends the new token with the response,
  * oAuth callback.  Encrypts the access token and sends the new token with the response,
- * and redirects to redirect url.
  */
  */
 const tokenService = require('../helpers/jwt')
 const tokenService = require('../helpers/jwt')
-const parseUrl = require('url').parse
-const { hasMatch, sanitizeHtml } = require('../helpers/utils')
-const oAuthState = require('../helpers/oauth-state')
 const logger = require('../logger')
 const logger = require('../logger')
 
 
 /**
 /**
@@ -25,29 +21,5 @@ module.exports = function callback (req, res, next) {
   req.uppy.providerTokens[providerName] = req.query.access_token
   req.uppy.providerTokens[providerName] = req.query.access_token
   logger.debug(`Generating auth token for provider ${providerName}.`)
   logger.debug(`Generating auth token for provider ${providerName}.`)
   const uppyAuthToken = tokenService.generateToken(req.uppy.providerTokens, req.uppy.options.secret)
   const uppyAuthToken = tokenService.generateToken(req.uppy.providerTokens, req.uppy.options.secret)
-  // add the token to cookies for thumbnail/image requests
-  tokenService.addToCookies(res, uppyAuthToken, req.uppy.options)
-
-  const state = (req.session.grant || {}).state
-  if (state) {
-    const origin = oAuthState.getFromState(state, 'origin', req.uppy.options.secret)
-    const allowedClients = req.uppy.options.clients
-    // if no preset clients then allow any client
-    if (!allowedClients || hasMatch(origin, allowedClients) || hasMatch(parseUrl(origin).host, allowedClients)) {
-      return res.send(`
-        <!DOCTYPE html>
-        <html>
-        <head>
-            <meta charset="utf-8" />
-            <script>
-              window.opener.postMessage({token: "${uppyAuthToken}"}, "${sanitizeHtml(origin)}")
-              window.close()
-            </script>
-        </head>
-        <body></body>
-        </html>`
-      )
-    }
-  }
-  next()
+  return res.redirect(req.uppy.buildURL(`/${providerName}/send-token?uppyAuthToken=${uppyAuthToken}`, true))
 }
 }

+ 1 - 0
packages/@uppy/companion/src/server/controllers/index.js

@@ -1,6 +1,7 @@
 module.exports = {
 module.exports = {
   authorized: require('./authorized'),
   authorized: require('./authorized'),
   callback: require('./callback'),
   callback: require('./callback'),
+  sendToken: require('./send-token'),
   get: require('./get'),
   get: require('./get'),
   thumbnail: require('./thumbnail'),
   thumbnail: require('./thumbnail'),
   list: require('./list'),
   list: require('./list'),

+ 51 - 0
packages/@uppy/companion/src/server/controllers/send-token.js

@@ -0,0 +1,51 @@
+/**
+ *
+ * sends auth token to uppy client
+ */
+const tokenService = require('../helpers/jwt')
+const parseUrl = require('url').parse
+const { hasMatch, sanitizeHtml } = require('../helpers/utils')
+const oAuthState = require('../helpers/oauth-state')
+
+/**
+ *
+ * @param {object} req
+ * @param {object} res
+ * @param {function} next
+ */
+module.exports = function sendToken (req, res, next) {
+  const uppyAuthToken = req.uppy.authToken
+  // add the token to cookies for thumbnail/image requests
+  tokenService.addToCookies(res, uppyAuthToken, req.uppy.options)
+
+  const state = (req.session.grant || {}).state
+  if (state) {
+    const origin = oAuthState.getFromState(state, 'origin', req.uppy.options.secret)
+    const allowedClients = req.uppy.options.clients
+    // if no preset clients then allow any client
+    if (!allowedClients || hasMatch(origin, allowedClients) || hasMatch(parseUrl(origin).host, allowedClients)) {
+      return res.send(htmlContent(uppyAuthToken, origin))
+    }
+  }
+  next()
+}
+
+/**
+ *
+ * @param {string} token uppy auth token
+ * @param {string} origin url string
+ */
+const htmlContent = (token, origin) => {
+  return `
+    <!DOCTYPE html>
+    <html>
+    <head>
+        <meta charset="utf-8" />
+        <script>
+          window.opener.postMessage({token: "${token}"}, "${sanitizeHtml(origin)}")
+          window.close()
+        </script>
+    </head>
+    <body></body>
+    </html>`
+}

+ 2 - 1
packages/@uppy/companion/src/uppy.js

@@ -87,6 +87,7 @@ module.exports.app = (options = {}) => {
   app.get('/:providerName/redirect', middlewares.hasSessionAndProvider, controllers.redirect)
   app.get('/:providerName/redirect', middlewares.hasSessionAndProvider, controllers.redirect)
   app.get('/:providerName/logout', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.logout)
   app.get('/:providerName/logout', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.logout)
   app.get('/:providerName/authorized', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.authorized)
   app.get('/:providerName/authorized', middlewares.hasSessionAndProvider, middlewares.gentleVerifyToken, controllers.authorized)
+  app.get('/:providerName/send-token', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.sendToken)
   app.get('/:providerName/list/:id?', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.list)
   app.get('/:providerName/list/:id?', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.list)
   app.post('/:providerName/get/:id', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.get)
   app.post('/:providerName/get/:id', middlewares.hasSessionAndProvider, middlewares.verifyToken, controllers.get)
   app.get('/:providerName/thumbnail/:id', middlewares.hasSessionAndProvider, middlewares.cookieAuthToken, middlewares.verifyToken, controllers.thumbnail)
   app.get('/:providerName/thumbnail/:id', middlewares.hasSessionAndProvider, middlewares.cookieAuthToken, middlewares.verifyToken, controllers.thumbnail)
@@ -217,7 +218,7 @@ const getOptionsMiddleware = (options) => {
     req.uppy = {
     req.uppy = {
       options,
       options,
       s3Client,
       s3Client,
-      authToken: req.header('uppy-auth-token'),
+      authToken: req.header('uppy-auth-token') || req.query.uppyAuthToken,
       buildURL: getURLBuilder(options)
       buildURL: getURLBuilder(options)
     }
     }
     next()
     next()

+ 22 - 13
packages/@uppy/companion/test/__tests__/companion.js

@@ -66,26 +66,35 @@ describe('download provdier file', () => {
 })
 })
 
 
 describe('test authentication', () => {
 describe('test authentication', () => {
-  test('authentication callback redirects to specified url', () => {
+  test('authentication callback redirects to send-token url', () => {
     return request(authServer)
     return request(authServer)
       .get('/drive/callback')
       .get('/drive/callback')
-      .set('uppy-auth-token', token)
+      .expect(302)
+      .expect((res) => {
+        expect(res.header['location']).toContain('http://localhost:3020/drive/send-token?uppyAuthToken=')
+      })
+  })
+
+  test('the token gets sent via cookie and html', () => {
+    return request(authServer)
+      .get(`/drive/send-token?uppyAuthToken=${token}`)
       .expect(200)
       .expect(200)
       .expect((res) => {
       .expect((res) => {
         const authToken = res.header['set-cookie'][0].split(';')[0].split('uppyAuthToken=')[1]
         const authToken = res.header['set-cookie'][0].split(';')[0].split('uppyAuthToken=')[1]
+        expect(authToken).toEqual(token)
         // see mock ../../src/server/helpers/oauth-state above for http://localhost:3020
         // see mock ../../src/server/helpers/oauth-state above for http://localhost:3020
         const body = `
         const body = `
-        <!DOCTYPE html>
-        <html>
-        <head>
-            <meta charset="utf-8" />
-            <script>
-              window.opener.postMessage({token: "${authToken}"}, "http://localhost:3020")
-              window.close()
-            </script>
-        </head>
-        <body></body>
-        </html>`
+    <!DOCTYPE html>
+    <html>
+    <head>
+        <meta charset="utf-8" />
+        <script>
+          window.opener.postMessage({token: "${token}"}, "http://localhost:3020")
+          window.close()
+        </script>
+    </head>
+    <body></body>
+    </html>`
         expect(res.text).toBe(body)
         expect(res.text).toBe(body)
       })
       })
   })
   })

+ 1 - 1
packages/@uppy/companion/test/mockserver.js

@@ -5,7 +5,7 @@ const session = require('express-session')
 var authServer = express()
 var authServer = express()
 
 
 authServer.use(session({ secret: 'grant', resave: true, saveUninitialized: true }))
 authServer.use(session({ secret: 'grant', resave: true, saveUninitialized: true }))
-authServer.all('/drive/callback', (req, res, next) => {
+authServer.all('/drive/send-token', (req, res, next) => {
   req.session.grant = {
   req.session.grant = {
     state: 'non-empty-value' }
     state: 'non-empty-value' }
   next()
   next()

+ 3 - 1
packages/@uppy/dropbox/src/index.js

@@ -20,7 +20,9 @@ module.exports = class Dropbox extends Plugin {
     this.provider = new Provider(uppy, {
     this.provider = new Provider(uppy, {
       serverUrl: this.opts.serverUrl,
       serverUrl: this.opts.serverUrl,
       serverHeaders: this.opts.serverHeaders,
       serverHeaders: this.opts.serverHeaders,
-      provider: 'dropbox'
+      storage: this.opts.storage,
+      provider: 'dropbox',
+      pluginId: this.id
     })
     })
 
 
     this.onAuth = this.onAuth.bind(this)
     this.onAuth = this.onAuth.bind(this)

+ 3 - 1
packages/@uppy/google-drive/src/index.js

@@ -23,8 +23,10 @@ module.exports = class GoogleDrive extends Plugin {
     this.provider = new Provider(uppy, {
     this.provider = new Provider(uppy, {
       serverUrl: this.opts.serverUrl,
       serverUrl: this.opts.serverUrl,
       serverHeaders: this.opts.serverHeaders,
       serverHeaders: this.opts.serverHeaders,
+      storage: this.opts.storage,
       provider: 'drive',
       provider: 'drive',
-      authProvider: 'google'
+      authProvider: 'google',
+      pluginId: this.id
     })
     })
 
 
     this.onAuth = this.onAuth.bind(this)
     this.onAuth = this.onAuth.bind(this)

+ 3 - 1
packages/@uppy/instagram/src/index.js

@@ -20,8 +20,10 @@ module.exports = class Instagram extends Plugin {
     this.provider = new Provider(uppy, {
     this.provider = new Provider(uppy, {
       serverUrl: this.opts.serverUrl,
       serverUrl: this.opts.serverUrl,
       serverHeaders: this.opts.serverHeaders,
       serverHeaders: this.opts.serverHeaders,
+      storage: this.opts.storage,
       provider: 'instagram',
       provider: 'instagram',
-      authProvider: 'instagram'
+      authProvider: 'instagram',
+      pluginId: this.id
     })
     })
 
 
     this.onAuth = this.onAuth.bind(this)
     this.onAuth = this.onAuth.bind(this)