Prechádzať zdrojové kódy

@uppy/companion: fix merge conflicts

Antoine du Hamel 10 mesiacov pred
rodič
commit
0dd7ac35d8

+ 1 - 1
packages/@uppy/companion/src/server/provider/drive/index.js

@@ -9,7 +9,7 @@ const { ProviderAuthError } = require('../error')
 const got = require('../../got')
 
 // For testing refresh token:
-// first run a download with mockAccessTokenExpiredError = true
+// first run a download with mockAccessTokenExpiredError = true 
 // then when you want to test expiry, set to mockAccessTokenExpiredError to the logged access token
 // This will trigger companion/nodemon to restart, and it will respond with a simulated invalid token response
 const mockAccessTokenExpiredError = undefined

+ 6 - 6
packages/@uppy/companion/src/server/provider/google/drive/index.js

@@ -1,4 +1,4 @@
-const got = require('got').default
+const got = require('../../../got')
 
 const { logout, refreshToken } = require('../index')
 const logger = require('../../../logger')
@@ -23,7 +23,7 @@ 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 = '*'
 
-const getClient = ({ token }) => got.extend({
+const getClient = async ({ token }) => (await got).extend({
   prefixUrl: 'https://www.googleapis.com/drive/v3',
   headers: {
     authorization: `Bearer ${token}`,
@@ -31,7 +31,7 @@ const getClient = ({ token }) => got.extend({
 })
 
 async function getStats ({ id, token }) {
-  const client = getClient({ token })
+  const client = await getClient({ token })
 
   const getStatsInner = async (statsOfId) => (
     client.get(`files/${encodeURIComponent(statsOfId)}`, { searchParams: { fields: DRIVE_FILE_FIELDS, supportsAllDrives: true }, responseType: 'json' }).json()
@@ -66,7 +66,7 @@ class Drive extends Provider {
       const isRoot = directory === 'root'
       const isVirtualSharedDirRoot = directory === VIRTUAL_SHARED_DIR
 
-      const client = getClient({ token })
+      const client = await getClient({ token })
 
       async function fetchSharedDrives (pageToken = null) {
         const shouldListSharedDrives = isRoot && !query.cursor
@@ -136,7 +136,7 @@ class Drive extends Provider {
     }
 
     return withGoogleErrorHandling(Drive.authProvider, 'provider.drive.download.error', async () => {
-      const client = getClient({ token })
+      const client = await getClient({ token })
 
       const { mimeType, id, exportLinks } = await getStats({ id: idIn, token })
 
@@ -152,7 +152,7 @@ class Drive extends Provider {
         // Implemented based on the answer from StackOverflow: https://stackoverflow.com/a/59168288
         const mimeTypeExportLink = exportLinks?.[mimeType2]
         if (mimeTypeExportLink) {
-          const gSuiteFilesClient = got.extend({
+          const gSuiteFilesClient = (await got).extend({
             headers: {
               authorization: `Bearer ${token}`,
             },

+ 0 - 172
packages/@uppy/companion/src/server/provider/google/googlephotos/index.js

@@ -1,172 +0,0 @@
-const got = require('got').default
-
-const { logout, refreshToken } = require('../index')
-const { withGoogleErrorHandling } = require('../../providerErrors')
-const { prepareStream } = require('../../../helpers/utils')
-const { MAX_AGE_REFRESH_TOKEN } = require('../../../helpers/jwt')
-const logger = require('../../../logger')
-const Provider = require('../../Provider')
-
-
-const getBaseClient = ({ token }) => got.extend({
-  headers: {
-    authorization: `Bearer ${token}`,
-  },
-})
-
-const getPhotosClient = ({ token }) => getBaseClient({ token }).extend({
-  prefixUrl: 'https://photoslibrary.googleapis.com/v1',
-})
-
-const getOauthClient = ({ token }) => getBaseClient({ token }).extend({
-  prefixUrl: 'https://www.googleapis.com/oauth2/v1',
-})
-
-async function paginate(fn, getter, limit = 5) {
-  const items = []
-  let pageToken
-
-  for (let i = 0; (i === 0 || pageToken != null); i++) {
-    if (i >= limit) {
-      logger.warn(`Hit pagination limit of ${limit}`)
-      break;
-    }
-    const response = await fn(pageToken);
-    items.push(...getter(response));
-    pageToken = response.nextPageToken
-  }
-  return items
-}
-
-/**
- * Provider for Google Photos API
- */
-class GooglePhotos extends Provider {
-  static get authProvider () {
-    return 'googlephotos'
-  }
-
-  static get authStateExpiry () {
-    return MAX_AGE_REFRESH_TOKEN
-  }
-
-  // eslint-disable-next-line class-methods-use-this
-  async list (options) {
-    return withGoogleErrorHandling(GooglePhotos.authProvider, 'provider.photos.list.error', async () => {
-      const { directory, query } = options
-      const { token } = options
-
-      const isRoot = !directory
-
-      const client = getPhotosClient({ token })
-
-
-      async function fetchAlbums () {
-        if (!isRoot) return [] // albums are only in the root
-
-        return paginate(
-          (pageToken) => client.get('albums', { searchParams: { pageToken, pageSize: 50 }, responseType: 'json' }).json(),
-          (response) => response.albums,
-        )
-      }
-
-      async function fetchSharedAlbums () {
-        if (!isRoot) return [] // albums are only in the root
-
-        return paginate(
-          (pageToken) => client.get('sharedAlbums', { searchParams: { pageToken, pageSize: 50 }, responseType: 'json' }).json(),
-          (response) => response.sharedAlbums ?? [], // seems to be undefined if no shared albums
-        )
-      }
-
-      async function fetchMediaItems () {
-        if (isRoot) return { mediaItems: [] } // no images in root (album list only)
-        const resp = await client.post('mediaItems:search', { json: { pageToken: query?.cursor, albumId: directory, pageSize: 50 }, responseType: 'json' }).json();
-        return resp
-      }
-
-      const [sharedAlbums, albums, { mediaItems, nextPageToken }] = await Promise.all([
-        fetchSharedAlbums(), fetchAlbums(), fetchMediaItems()
-      ])
-
-      const newSp = new URLSearchParams(Object.entries(query));
-      if (nextPageToken) newSp.set('cursor', nextPageToken);
-
-      const iconSize = 64
-      const thumbSize = 300
-      const getIcon = (baseUrl) => `${baseUrl}=w${iconSize}-h${iconSize}-c`
-      const getThumbnail = (baseUrl) => `${baseUrl}=w${thumbSize}-h${thumbSize}-c`
-      const adaptedItems = [
-        ...albums.map((album) => ({
-          isFolder: true,
-          icon: 'https://drive-thirdparty.googleusercontent.com/32/type/application/vnd.google-apps.folder',
-          mimeType: 'application/vnd.google-apps.folder',
-          thumbnail: getThumbnail(album.coverPhotoBaseUrl),
-          name: album.title,
-          id: album.id,
-          requestPath: album.id,
-        })),
-        ...sharedAlbums.map((sharedAlbum) => ({
-          isFolder: true,
-          icon: 'https://drive-thirdparty.googleusercontent.com/32/type/application/vnd.google-apps.folder',
-          mimeType: 'application/vnd.google-apps.folder',
-          thumbnail: getThumbnail(sharedAlbum.coverPhotoBaseUrl),
-          name: sharedAlbum.title,
-          id: sharedAlbum.id,
-          requestPath: sharedAlbum.id,
-        })),
-        ...mediaItems.map((mediaItem) => ({
-          isFolder: false,
-          icon: getIcon(mediaItem.baseUrl),
-          thumbnail: getThumbnail(mediaItem.baseUrl),
-          name: mediaItem.filename,
-          id: mediaItem.id,
-          mimeType: mediaItem.mimeType,
-          modifiedDate: mediaItem.creationTime,
-          requestPath: mediaItem.id,
-          custom: {
-            imageWidth: mediaItem.photo ? mediaItem.width : undefined,
-            imageHeight: mediaItem.photo ? mediaItem.height : undefined,
-            videoWidth: mediaItem.video ? mediaItem.width : undefined,
-            videoHeight: mediaItem.video ? mediaItem.height : undefined,
-          },
-        })),
-      ];
-
-      const { email: username } = await getOauthClient({ token }).get('userinfo').json()
-
-      return {
-        username,
-        items: adaptedItems,
-        nextPagePath: newSp.size > 0 ? `${directory ?? ''}?${newSp.toString()}` : null,
-      }
-    })
-  }
-
-  // eslint-disable-next-line class-methods-use-this
-  async download ({ id, token }) {
-    return withGoogleErrorHandling(GooglePhotos.authProvider, 'provider.photos.download.error', async () => {
-      const client = getPhotosClient({ token })
-
-      const { baseUrl } = await client.get(`mediaItems/${encodeURIComponent(id)}`, { responseType: 'json' }).json()
-
-      const url = `${baseUrl}=d`;
-      const stream = got.stream.get(url, { responseType: 'json' })
-      const { size } = await prepareStream(stream)
-
-      return { stream, size }
-    })
-  }
-
-  // eslint-disable-next-line class-methods-use-this
-  async logout(...args) {
-    return logout(...args)
-  }
-
-  // eslint-disable-next-line class-methods-use-this
-  async refreshToken(...args) {
-    return refreshToken(...args)
-  }
-}
-
-module.exports = GooglePhotos

+ 4 - 4
packages/@uppy/companion/src/server/provider/google/index.js

@@ -1,4 +1,4 @@
-const got = require('got').default
+const got = require('../../got')
 
 
 const { withGoogleErrorHandling } = require('../providerErrors')
@@ -8,20 +8,20 @@ const { withGoogleErrorHandling } = require('../providerErrors')
  * Reusable google stuff
  */
 
-const getOauthClient = () => got.extend({
+const getOauthClient = async () => (await got).extend({
   prefixUrl: 'https://oauth2.googleapis.com',
 })
 
 async function refreshToken({ clientId, clientSecret, refreshToken: theRefreshToken }) {
   return withGoogleErrorHandling('google', 'provider.google.token.refresh.error', async () => {
-    const { access_token: accessToken } = await getOauthClient().post('token', { responseType: 'json', form: { refresh_token: theRefreshToken, grant_type: 'refresh_token', client_id: clientId, client_secret: clientSecret } }).json()
+    const { access_token: accessToken } = await (await getOauthClient()).post('token', { responseType: 'json', form: { refresh_token: theRefreshToken, grant_type: 'refresh_token', client_id: clientId, client_secret: clientSecret } }).json()
     return { accessToken }
   })
 }
 
 async function logout({ token }) {
   return withGoogleErrorHandling('google', 'provider.google.logout.error', async () => {
-    await got.post('https://accounts.google.com/o/oauth2/revoke', {
+    await (await got).post('https://accounts.google.com/o/oauth2/revoke', {
       searchParams: { token },
       responseType: 'json',
     })

+ 14 - 1
packages/@uppy/companion/src/server/provider/providerErrors.js

@@ -68,4 +68,17 @@ async function withProviderErrorHandling({
   }
 }
 
-module.exports = { withProviderErrorHandling }
+async function withGoogleErrorHandling (providerName, tag, fn) {
+  return withProviderErrorHandling({
+    fn,
+    tag,
+    providerName,
+    isAuthError: (response) => (
+      response.statusCode === 401
+      || (response.statusCode === 400 && response.body?.error === 'invalid_grant') // Refresh token has expired or been revoked
+    ),
+    getJsonErrorMessage: (body) => body?.error?.message,
+  })
+}
+
+module.exports = { withProviderErrorHandling, withGoogleErrorHandling }