Skip to content

Commit

Permalink
@uppy/google-photos: add plugin (#5265)
Browse files Browse the repository at this point in the history
Backport of #5061
  • Loading branch information
aduh95 committed Jun 19, 2024
1 parent 0dd7ac3 commit 12cf278
Show file tree
Hide file tree
Showing 18 changed files with 391 additions and 526 deletions.
39 changes: 27 additions & 12 deletions packages/@uppy/companion/src/config/grant.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
const google = {
transport: 'session',

// access_type: offline is needed in order to get refresh tokens.
// prompt: 'consent' is needed because sometimes a user will get stuck in an authenticated state where we will
// receive no refresh tokens from them. This seems to be happen when running on different subdomains.
// therefore to be safe that we always get refresh tokens, we set this.
// https://stackoverflow.com/questions/10827920/not-receiving-google-oauth-refresh-token/65108513#65108513
custom_params: { access_type : 'offline', prompt: 'consent' },

// copied from https://github.com/simov/grant/blob/master/config/oauth.json
"authorize_url": "https://accounts.google.com/o/oauth2/v2/auth",
"access_url": "https://oauth2.googleapis.com/token",
"oauth": 2,
"scope_delimiter": " "
}

// oauth configuration for provider services that are used.
module.exports = () => {
return {
// for drive
google: {
transport: 'session',
scope: [
'https://www.googleapis.com/auth/drive.readonly',
],
// we need separate auth providers because scopes are different,
// and because it would be a too big rewrite to allow reuse of the same provider.
googledrive: {
...google,
callback: '/drive/callback',
// access_type: offline is needed in order to get refresh tokens.
// prompt: 'consent' is needed because sometimes a user will get stuck in an authenticated state where we will
// receive no refresh tokens from them. This seems to be happen when running on different subdomains.
// therefore to be safe that we always get refresh tokens, we set this.
// https://stackoverflow.com/questions/10827920/not-receiving-google-oauth-refresh-token/65108513#65108513
custom_params: { access_type : 'offline', prompt: 'consent' },
scope: ['https://www.googleapis.com/auth/drive.readonly'],
},
googlephotos: {
...google,
callback: '/googlephotos/callback',
scope: ['https://www.googleapis.com/auth/photoslibrary.readonly', 'https://www.googleapis.com/auth/userinfo.email'], // if name is needed, then add https://www.googleapis.com/auth/userinfo.profile too
},
dropbox: {
transport: 'session',
Expand Down
5 changes: 1 addition & 4 deletions packages/@uppy/companion/src/server/controllers/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ async function get (req, res) {
return provider.size({ id, token: accessToken, query: req.query })
}

async function download () {
const { stream } = await provider.download({ id, token: accessToken, providerUserSession, query: req.query })
return stream
}
const download = () => provider.download({ id, token: accessToken, providerUserSession, query: req.query })

try {
await startDownUpload({ req, res, getSize, download })
Expand Down
8 changes: 3 additions & 5 deletions packages/@uppy/companion/src/server/controllers/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ const downloadURL = async (url, allowLocalIPs, traceId) => {
try {
const protectedGot = await getProtectedGot({ allowLocalIPs })
const stream = protectedGot.stream.get(url, { responseType: 'json' })
await prepareStream(stream)
return stream
const { size } = await prepareStream(stream)
return { stream, size }
} catch (err) {
logger.error(err, 'controller.url.download.error', traceId)
throw err
Expand Down Expand Up @@ -77,9 +77,7 @@ const get = async (req, res) => {
return size
}

async function download () {
return downloadURL(req.body.url, allowLocalUrls, req.id)
}
const download = () => downloadURL(req.body.url, allowLocalUrls, req.id)

try {
await startDownUpload({ req, res, getSize, download })
Expand Down
4 changes: 2 additions & 2 deletions packages/@uppy/companion/src/server/helpers/oauth-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports.encodeState = (state, secret) => {
return encrypt(encodedState, secret)
}

const decodeState = (state, secret) => {
module.exports.decodeState = (state, secret) => {
const encodedState = decrypt(state, secret)
return JSON.parse(atob(encodedState))
}
Expand All @@ -18,7 +18,7 @@ module.exports.generateState = () => {
}

module.exports.getFromState = (state, name, secret) => {
return decodeState(state, secret)[name]
return module.exports.decodeState(state, secret)[name]
}

module.exports.getGrantDynamicFromRequest = (req) => {
Expand Down
16 changes: 12 additions & 4 deletions packages/@uppy/companion/src/server/helpers/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ const { respondWithError } = require('../provider/error')

async function startDownUpload({ req, res, getSize, download }) {
try {
const size = await getSize()
logger.debug('Starting download stream.', null, req.id)
const { stream, size: maybeSize } = await download()

let size
// if the provider already knows the size, we can use that
if (typeof maybeSize === 'number' && !Number.isNaN(maybeSize) && maybeSize > 0) {
size = maybeSize
}
// if not we need to get the size
if (size == null) {
size = await getSize()
}
const { clientSocketConnectTimeout } = req.companion.options

logger.debug('Instantiating uploader.', null, req.id)
const uploader = new Uploader(Uploader.reqToOptions(req, size))

logger.debug('Starting download stream.', null, req.id)
const stream = await download()

// "Forking" off the upload operation to background, so we can return the http request:
; (async () => {
// wait till the client has connected to the socket, before starting
Expand Down
7 changes: 5 additions & 2 deletions packages/@uppy/companion/src/server/helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,14 @@ module.exports.StreamHttpJsonError = StreamHttpJsonError

module.exports.prepareStream = async (stream) => new Promise((resolve, reject) => {
stream
.on('response', () => {
.on('response', (response) => {
const contentLengthStr = response.headers['content-length']
const contentLength = parseInt(contentLengthStr, 10);
const size = !Number.isNaN(contentLength) && contentLength >= 0 ? contentLength : undefined;
// Don't allow any more data to flow yet.
// https://github.com/request/request/issues/1990#issuecomment-184712275
stream.pause()
resolve()
resolve({ size })
})
.on('error', (err) => {
// In this case the error object is not a normal GOT HTTPError where json is already parsed,
Expand Down
190 changes: 0 additions & 190 deletions packages/@uppy/companion/src/server/provider/drive/adapter.js

This file was deleted.

Loading

0 comments on commit 12cf278

Please sign in to comment.