mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-18 00:55:35 +00:00
Merge pull request #824 from transloadit/cookieless-server-token
refactor: use local storage to store provider token
This commit is contained in:
commit
c2b5f0b66a
7 changed files with 90 additions and 93 deletions
|
|
@ -84,6 +84,11 @@ module.exports = class Instagram extends Plugin {
|
|||
}
|
||||
|
||||
getItemIcon (item) {
|
||||
if (!item.images) {
|
||||
return <svg viewBox="0 0 58 58" opacity="0.6">
|
||||
<path d="M36.537 28.156l-11-7a1.005 1.005 0 0 0-1.02-.033C24.2 21.3 24 21.635 24 22v14a1 1 0 0 0 1.537.844l11-7a1.002 1.002 0 0 0 0-1.688zM26 34.18V23.82L34.137 29 26 34.18z" /><path d="M57 6H1a1 1 0 0 0-1 1v44a1 1 0 0 0 1 1h56a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1zM10 28H2v-9h8v9zm-8 2h8v9H2v-9zm10 10V8h34v42H12V40zm44-12h-8v-9h8v9zm-8 2h8v9h-8v-9zm8-22v9h-8V8h8zM2 8h8v9H2V8zm0 42v-9h8v9H2zm54 0h-8v-9h8v9z" />
|
||||
</svg>
|
||||
}
|
||||
return <img src={item.images.thumbnail.url} />
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const Plugin = require('../core/Plugin')
|
||||
const tus = require('tus-js-client')
|
||||
const UppySocket = require('../core/UppySocket')
|
||||
const Provider = require('../server/Provider')
|
||||
const {
|
||||
emitSocketProgress,
|
||||
getSocketHost,
|
||||
|
|
@ -238,31 +239,21 @@ module.exports = class Tus extends Plugin {
|
|||
.catch(reject)
|
||||
}
|
||||
|
||||
fetch(file.remote.url, {
|
||||
method: 'post',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(Object.assign({}, file.remote.body, {
|
||||
this.uppy.emit('upload-started', file)
|
||||
const provider = new Provider(this.uppy, file.remote.providerOptions)
|
||||
provider.post(
|
||||
file.remote.url,
|
||||
Object.assign({}, file.remote.body, {
|
||||
endpoint: opts.endpoint,
|
||||
uploadUrl: opts.uploadUrl,
|
||||
protocol: 'tus',
|
||||
size: file.data.size,
|
||||
metadata: file.meta
|
||||
}))
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.status < 200 || res.status > 300) {
|
||||
return reject(res.statusText)
|
||||
}
|
||||
|
||||
return res.json().then((data) => {
|
||||
this.uppy.setFileState(file.id, { serverToken: data.token })
|
||||
file = this.uppy.getFile(file.id)
|
||||
return file
|
||||
})
|
||||
).then((res) => {
|
||||
this.uppy.setFileState(file.id, { serverToken: res.token })
|
||||
file = this.uppy.getFile(file.id)
|
||||
return file
|
||||
})
|
||||
.then((file) => {
|
||||
return this.connectToServerSocket(file)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ const { h } = require('preact')
|
|||
const { RequestClient } = require('../../server')
|
||||
const UrlUI = require('./UrlUI.js')
|
||||
const { toArray } = require('../../core/Utils')
|
||||
require('whatwg-fetch')
|
||||
|
||||
/**
|
||||
* Url
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ const Plugin = require('../core/Plugin')
|
|||
const cuid = require('cuid')
|
||||
const Translator = require('../core/Translator')
|
||||
const UppySocket = require('../core/UppySocket')
|
||||
const Provider = require('../server/Provider')
|
||||
const {
|
||||
emitSocketProgress,
|
||||
getSocketHost,
|
||||
|
|
@ -310,49 +311,39 @@ module.exports = class XHRUpload extends Plugin {
|
|||
fields[name] = file.meta[name]
|
||||
})
|
||||
|
||||
fetch(file.remote.url, {
|
||||
method: 'post',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(Object.assign({}, file.remote.body, {
|
||||
const provider = new Provider(this.uppy, file.remote.providerOptions)
|
||||
provider.post(
|
||||
file.remote.url,
|
||||
Object.assign({}, file.remote.body, {
|
||||
endpoint: opts.endpoint,
|
||||
size: file.data.size,
|
||||
fieldname: opts.fieldName,
|
||||
metadata: fields,
|
||||
headers: opts.headers
|
||||
}))
|
||||
})
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.status < 200 && res.status > 300) {
|
||||
return reject(res.statusText)
|
||||
}
|
||||
const token = res.token
|
||||
const host = getSocketHost(file.remote.host)
|
||||
const socket = new UppySocket({ target: `${host}/api/${token}` })
|
||||
|
||||
res.json().then((data) => {
|
||||
const token = data.token
|
||||
const host = getSocketHost(file.remote.host)
|
||||
const socket = new UppySocket({ target: `${host}/api/${token}` })
|
||||
socket.on('progress', (progressData) => emitSocketProgress(this, progressData, file))
|
||||
|
||||
socket.on('progress', (progressData) => emitSocketProgress(this, progressData, file))
|
||||
socket.on('success', (data) => {
|
||||
const resp = opts.getResponseData(data.response.responseText, data.response)
|
||||
const uploadURL = resp[opts.responseUrlFieldName]
|
||||
this.uppy.emit('upload-success', file, resp, uploadURL)
|
||||
socket.close()
|
||||
return resolve()
|
||||
})
|
||||
|
||||
socket.on('success', (data) => {
|
||||
const resp = opts.getResponseData(data.response.responseText, data.response)
|
||||
const uploadURL = resp[opts.responseUrlFieldName]
|
||||
this.uppy.emit('upload-success', file, resp, uploadURL)
|
||||
socket.close()
|
||||
return resolve()
|
||||
})
|
||||
|
||||
socket.on('error', (errData) => {
|
||||
const resp = errData.response
|
||||
const error = resp
|
||||
? opts.getResponseError(resp.responseText, resp)
|
||||
: Object.assign(new Error(errData.error.message), { cause: errData.error })
|
||||
this.uppy.emit('upload-error', file, error)
|
||||
reject(error)
|
||||
})
|
||||
socket.on('error', (errData) => {
|
||||
const resp = errData.response
|
||||
const error = resp
|
||||
? opts.getResponseError(resp.responseText, resp)
|
||||
: Object.assign(new Error(errData.error.message), { cause: errData.error })
|
||||
this.uppy.emit('upload-error', file, error)
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,6 +14,17 @@ module.exports = class Provider extends RequestClient {
|
|||
this.id = this.provider
|
||||
this.authProvider = opts.authProvider || this.provider
|
||||
this.name = this.opts.name || _getName(this.id)
|
||||
this.tokenKey = `uppy-server-${this.id}-auth-token`
|
||||
}
|
||||
|
||||
get defaultHeaders () {
|
||||
return Object.assign({}, super.defaultHeaders, {'uppy-auth-token': localStorage.getItem(this.tokenKey)})
|
||||
}
|
||||
|
||||
// @todo(i.olarewaju) consider whether or not this method should be exposed
|
||||
setAuthToken (token) {
|
||||
// @todo(i.olarewaju) add fallback for OOM storage
|
||||
localStorage.setItem(this.tokenKey, token)
|
||||
}
|
||||
|
||||
checkAuth () {
|
||||
|
|
@ -37,5 +48,9 @@ module.exports = class Provider extends RequestClient {
|
|||
|
||||
logout (redirect = location.href) {
|
||||
return this.get(`${this.id}/logout?redirect=${redirect}`)
|
||||
.then((res) => {
|
||||
localStorage.removeItem(this.tokenKey)
|
||||
return res
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@ module.exports = class RequestClient {
|
|||
return uppyServer && uppyServer[host] ? uppyServer[host] : host
|
||||
}
|
||||
|
||||
get defaultHeaders () {
|
||||
return {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
|
||||
onReceiveResponse (response) {
|
||||
const state = this.uppy.getState()
|
||||
const uppyServer = state.uppyServer || {}
|
||||
|
|
@ -32,13 +39,9 @@ module.exports = class RequestClient {
|
|||
}
|
||||
|
||||
get (path) {
|
||||
return fetch(`${this.hostname}/${path}`, {
|
||||
return fetch(this._getUrl(path), {
|
||||
method: 'get',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
headers: this.defaultHeaders
|
||||
})
|
||||
// @todo validate response status before calling json
|
||||
.then(this.onReceiveResponse)
|
||||
|
|
@ -46,18 +49,25 @@ module.exports = class RequestClient {
|
|||
}
|
||||
|
||||
post (path, data) {
|
||||
return fetch(`${this.hostname}/${path}`, {
|
||||
return fetch(this._getUrl(path), {
|
||||
method: 'post',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
headers: this.defaultHeaders,
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(this.onReceiveResponse)
|
||||
// @todo validate response status before calling json
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (res.status < 200 || res.status > 300) {
|
||||
throw new Error(res.statusText)
|
||||
}
|
||||
return res.json()
|
||||
})
|
||||
}
|
||||
|
||||
_getUrl (url) {
|
||||
if (/^https?:/.test(url)) {
|
||||
return url
|
||||
}
|
||||
return `${this.hostname}/${url}`
|
||||
}
|
||||
|
||||
delete (path, data) {
|
||||
|
|
|
|||
|
|
@ -186,7 +186,8 @@ module.exports = class ProviderView {
|
|||
url: `${this.Provider.fileUrl(this.plugin.getItemRequestPath(file))}`,
|
||||
body: {
|
||||
fileId: this.plugin.getItemId(file)
|
||||
}
|
||||
},
|
||||
providerOptions: this.Provider.opts
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -446,35 +447,20 @@ module.exports = class ProviderView {
|
|||
}
|
||||
|
||||
handleAuth () {
|
||||
const urlId = Math.floor(Math.random() * 999999) + 1
|
||||
const redirect = `${location.href}${location.search ? '&' : '?'}id=${urlId}`
|
||||
|
||||
const authState = btoa(JSON.stringify({ redirect }))
|
||||
const authState = btoa(JSON.stringify({ origin: location.origin }))
|
||||
const link = `${this.Provider.authUrl()}?state=${authState}`
|
||||
|
||||
const authWindow = window.open(link, '_blank')
|
||||
authWindow.opener = null
|
||||
const checkAuth = () => {
|
||||
let authWindowUrl
|
||||
|
||||
try {
|
||||
authWindowUrl = authWindow.location.href
|
||||
} catch (e) {
|
||||
if (e instanceof DOMException || e instanceof TypeError) {
|
||||
return setTimeout(checkAuth, 100)
|
||||
} else throw e
|
||||
}
|
||||
|
||||
// split url because chrome adds '#' to redirects
|
||||
if (authWindowUrl && authWindowUrl.split('#')[0] === redirect) {
|
||||
authWindow.close()
|
||||
this._loaderWrapper(this.Provider.checkAuth(), this.plugin.onAuth, this.handleError)
|
||||
} else {
|
||||
setTimeout(checkAuth, 100)
|
||||
const handleToken = (e) => {
|
||||
if (e.origin !== this.plugin.opts.host || e.source !== authWindow) {
|
||||
return
|
||||
}
|
||||
authWindow.close()
|
||||
window.removeEventListener('message', handleToken)
|
||||
this.Provider.setAuthToken(e.data.token)
|
||||
this._loaderWrapper(this.Provider.checkAuth(), this.plugin.onAuth, this.handleError)
|
||||
}
|
||||
|
||||
checkAuth()
|
||||
window.addEventListener('message', handleToken)
|
||||
}
|
||||
|
||||
handleError (error) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue