Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Google Picker #5532

Open
2 of 11 tasks
mifi opened this issue Dec 2, 2024 · 12 comments
Open
2 of 11 tasks

Improve Google Picker #5532

mifi opened this issue Dec 2, 2024 · 12 comments
Labels

Comments

@mifi
Copy link
Contributor

mifi commented Dec 2, 2024

Collection of bugs and potential improvements remaining for Google Picker (Photos/Drive) after initial implementation in #5443:

Bugs

Improvements

  • allow selecting folders? setSelectFolderEnabled(true)
  • baseUrls expire after 60 minutes (google photos), so we might have to refresh them if an upload takes very long
  • implement logout method on provider (so that the provider gets an upload button in the top right like normal providers do)
  • include more metadata
    • width,height
    • thumbnail preview (not really possible it seems)
  • Possibility for backend OAuth2 flow in Companion Improve Google Picker #5532 (comment)
  • Export google docs and sheets as different format Improve Google Picker #5532 (comment) Improve Google Picker #5532 (comment)
@mifi mifi added the Feature label Dec 2, 2024
@mifi mifi mentioned this issue Dec 2, 2024
15 tasks
@StrixOSG
Copy link

StrixOSG commented Dec 2, 2024

An aside, and maybe this is a separate fix potentially but I noticed in the other PR #5443 the permission requested for Google Drive is: https://www.googleapis.com/auth/drive.readonly in https://github.com/transloadit/uppy/blob/988cc2d0b20d78fee9b8a607627f1188e0dd159a/packages/%40uppy/provider-views/src/GooglePicker/googlePicker.ts which is a restricted scope requiring CASA Tier 2 compliance.

This should likely be https://www.googleapis.com/auth/drive.file which is a non-restricted scope? As the other scope is restricted, which I believe is the reason we're switching to Google Picker?

EDIT: After testing with only https://www.googleapis.com/auth/drive.file I can confirm it works as expected however thumbnail previews of the images are not visible for Google Drive but it looks like that was solved here: https://community.transloadit.com/t/to-use-google-drive-you-must-pass-googles-tier-2-security-assessment/16701/8

Another update, it looks like since we're not actually getting the files and displaying them in a list with Uppy, there may not be much we can do here. After some research it might just be that you use https://www.googleapis.com/auth/drive.readonly and go through CASA Tier 2 compliance or use https://www.googleapis.com/auth/drive.file and also add .setMode(google.picker.DocsViewMode.LIST) so it looks marginally better then deal with thumbnails not displaying. Until Google fixes their issue since 2021: https://issuetracker.google.com/issues/208855070. Unless I'm missing something here? If not maybe the user could have the option here for which scope to use.

@mifi
Copy link
Contributor Author

mifi commented Dec 4, 2024

Wow I can't believe this has been broken since 2021. Makes it seem like nobody really uses the google picker api. anyways thanks for doing the research. I've created a PR to fix it here: #5535

@mifi
Copy link
Contributor Author

mifi commented Dec 4, 2024

I tried to see if I can show the Google Photos thumbnails in the Uppy UI but it seems to be not easily doable because the baseUrl that we get from google's GET mediaItems API needs the Bearer access token header, which an <img> cannot supply.
For Google Drive Picker we don't receive any thumbnail or image URL at all in the picked response.

@StrixOSG
Copy link

StrixOSG commented Dec 4, 2024

Wow I can't believe this has been broken since 2021. Makes it seem like nobody really uses the google picker api. anyways thanks for doing the research. I've created a PR to fix it here: #5535

I know. I responded too here on the issue and they said it's on the roadmap still but no ETA or timeline. Thanks for fixing that up!

While we're at it for improvements and nice to haves. I noticed that Google Docs and all that aren't converted anymore to .docx for example. In the regular/old implementation of Google Drive without picker it seems like they display as .docx instead of Google's .gdoc format. Is it possible to maybe have some conversion done when importing Companion side? Same with Google Sheets .xlsx

@mifi
Copy link
Contributor Author

mifi commented Dec 5, 2024

you mean the file extension in the uppy ui after selecting files?

@StrixOSG
Copy link

StrixOSG commented Dec 5, 2024

you mean the file extension in the uppy ui after selecting files?

So with the old implementation of Uppy Google Drive when you scrolled through the files (before selecting) the file extensions showed up as .docx and .xlsx but now for Google Picker it's downloading as .gdoc (it doesn't show the extension before selecting at all). I get that with Google Picker we don't have control over how the files display or what format they're in but was wondering if previously maybe there was some conversion done by Uppy in the previous Google Drive implementation to display and download as .docx rather then .gdoc? If so, potentially this could be done after selecting for Google Picker?

@GFoley83
Copy link

GFoley83 commented Dec 7, 2024

@mifi is it possible to extend the Uppy Google Picker client to optionally use Companion for the auth flow?

We work in a multi-tenant solution where every tenant has its own subdomain. This breaks the current Uppy Google Picker solution as the redirect from the Google auth popup comes back to that origin uri, not Companion.

The only possible way we could fix this currently would be to add every tenant to the Authorized redirect URIs in the Google console, which obviously we can't.

Alternatives here could be, we look after getting the auth token ourselves (not a problem) and then pass the token to Uppy somehow, but given this is what Companion is for, it feels like the better option.

@StrixOSG This can be done fairly easily during the picker callback. With our current, native Google Picker, we have:

const view = new window.google.picker.DocsView();
view.setMode(window.google.picker.DocsViewMode.LIST);

const sharedDrivesView = new window.google.picker.DocsView()
    .setEnableDrives(true)
    .setMode(window.google.picker.DocsViewMode.LIST)
    .setIncludeFolders(true); // creates just the shared drives view

const sharedWithMeView = new  window.google.picker.DocsView()
    .setMode(window.google.picker.DocsViewMode.LIST)
    .setOwnedByMe(false); // creates just the shared with me view

const picker = new window.google.picker.PickerBuilder()
    .setAppId("<project id>")
    .addView(view)
    .addView(sharedDrivesView)
    .addView(sharedWithMeView)
    .enableFeature(window.google.picker.Feature.MULTISELECT_ENABLED)
    .setMaxItems(10)
    .setOAuthToken(googleDriveAuthToken)
    .setCallback(pickerCallback) // Handle the response when files are selected
    .build();

picker.setVisible(true);

.  .  .

// Handle the Google Picker response
const pickerCallback = (data) => {
    if (data.action !== window.google.picker.Action.PICKED) {
        return;
    }
    Promise.all(data.docs.map(exportGDocsInStandardFormat))
};

const exportGDocsInStandardFormat = (doc) => {
    var url = "https://www.googleapis.com/drive/v3/files/" + doc.id;
    var mimeType = doc.mimeType;

    // Export Google Docs and Sheets as different formats, e.g., PDF or XLSX
    if (doc.mimeType.includes("google-apps.document")) {
        url += "/export?mimeType=application/pdf";
        mimeType = "application/pdf";
        doc.name += ".pdf";
    } else if (doc.mimeType.includes("google-apps.spreadsheet")) {
        url += "/export?mimeType=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        doc.name += ".xlsx";
    } else {
        url += "?alt=media";
    }

    var filename = doc.name;
    return {
        url,
        filename,
        mimeType,
    };
};

@StrixOSG
Copy link

StrixOSG commented Dec 9, 2024

Simply amazing @GFoley83! +1 to all of this @mifi for improvements

@devincowan
Copy link

devincowan commented Dec 11, 2024

+1 for sure on the picker implementation @mifi, thank you!

I gave it a try and am able to pick files from my Google Drive, however my picked files fail to upload.
After selecting a file, I see a 400 returned for a POST request to https://docs.google.com/picker/drivepreopen. The response looks like it has some odd parsing:
image

If I continue to "Upload" the picked file that got staged in Uppy, then I see a 500 response from a POST request to my companion server's: /google-picker/get
The response there is: {"message":"failed to fetch Google Picker URL"}
(Note I have COMPANION_ENABLE_GOOGLE_PICKER_ENDPOINT set true)

Companion logs:

::ffff:192.168.65.1 - - [11/Dec/2024:16:56:07 +0000] "POST /google-picker/get HTTP/1.1" 500 47 "http://localhost:8000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0"
::ffff:192.168.65.1 - - [11/Dec/2024:16:56:11 +0000] "OPTIONS /google-picker/get HTTP/1.1" 204 0 "http://localhost:8000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0"
companion: 2024-12-11T16:56:11.038Z [debug] null Google Picker file import handler running
companion: 2024-12-11T16:56:11.038Z [debug] null Starting download stream.
companion: 2024-12-11T16:56:11.265Z [error] controller.googlePicker.error HTTPError: Response code 404 (Not Found)
    at Request.<anonymous> (file:///app/node_modules/got/dist/source/as-promise/index.js:86:42)
    at Object.onceWrapper (node:events:629:26)
    at Request.emit (node:events:526:35)
    at Request._onResponseBase (file:///app/node_modules/got/dist/source/core/index.js:726:22)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Request._onResponse (file:///app/node_modules/got/dist/source/core/index.js:768:13) {
  input: undefined,
  code: 'ERR_NON_2XX_3XX_RESPONSE',

Has anyone else experienced being able to PICK files but having uploads fail after selection?

@mifi
Copy link
Contributor Author

mifi commented Dec 14, 2024

I gave it a try and am able to pick files from my Google Drive, however my picked files fail to upload.

Does this happen with all kinds of files, or some specific kind only? I don't know how to reproduce. Googling for drivepreopen doesn't yield many results:

We have limited capacity to work on this right now, so we need to prioritise. I will add all your suggestions/bugs to the OP of this issue.

@mifi
Copy link
Contributor Author

mifi commented Dec 18, 2024

I just spent a few hours trying to figure out why Google Drive is not working in production but works fine in testing mode. it's allowing me to pick files but when trying to download the files in the companion it got 404. Turns out that my setAppId() argument was wrong. What's more, google completely ignores the value passed to setAppId() in development but in production we just get a 404 if appID wrong without any indication of what's wrong. I was using project name from google console as app ID. Turns out we have to use project number instead of project name. https://stackoverflow.com/a/67335096/6519037

mifi added a commit to transloadit/uppy.io that referenced this issue Dec 18, 2024
@devincowan
Copy link

devincowan commented Dec 18, 2024

thanks @mifi using the project number resolved the issue for me! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants