feat: choose a Google Drive folder for experiment data - #156
Merged
Conversation
Backend for per-experiment Google Drive folder selection. The Picker UI (front-end, next) lets a researcher pick an existing Drive folder; these pieces let the picked folder become the experiment's data-folder parent instead of the fixed My Drive/DataPipe. - getProviderAccessToken (/api/getprovideraccesstoken): owner-authenticated endpoint returning a short-lived drive.file access token to the browser for Picker use, minted via resolve-token from the stored refresh token. Returns the access token only -- no refresh token or other user data. - gdriveProvider.createDataContainer: create the experiment folder under a researcher-supplied parentId when present; unchanged My Drive/DataPipe fallback when absent. - createExperiment: plumb optional parentFolderId through to the container. Additive and backward-compatible: parentFolderId is optional and the new endpoint is unused until the Picker UI lands. Emulator tests cover the endpoint's full auth/validation matrix and the parent-placement behavior (plus a default-path regression). Verified green (36/36) + clean build. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lets researchers optionally choose which existing Drive folder an
experiment's data folder is created in, via the Google Picker. If no
folder is chosen, behavior is unchanged (My Drive/DataPipe/<title>).
- lib/google-picker.js: isolated gapi/Picker loader (memoized, SSR-guarded)
exposing pickDriveFolder() -> { id, name } | null (cancel). Builds a
folder-only DocsView with setAppId so the drive.file grant ties to our
app and the picked folder is writable server-side later.
- pages/admin/new.js (gdrive path only): a "Choose Drive folder" button that
fetches a short-lived token from /api/getprovideraccesstoken, opens the
Picker, and stores the selection; passed to createProviderExperiment.
- createProviderExperiment forwards the optional parentFolderId.
- firebase-deploy-test.yml: NEXT_PUBLIC_GOOGLE_PICKER_API_KEY (referrer/API
restricted, browser-safe) + NEXT_PUBLIC_GDRIVE_PROJECT_NUMBER.
Tests: parentFolderId forwarding/omission, picker script single-injection +
PICKED/CANCEL paths; existing new-experiment-page regression intact.
Verified: 11/11 front-end tests green, build compiles.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Lets researchers optionally pick which existing Google Drive folder an experiment's data folder is created in, via the Google Picker. If no folder is chosen, behavior is unchanged (
My Drive/DataPipe/<title>). Per-experiment.Builds on the OAuth fix already on
test.Changes
Backend (
022c24a)POST /api/getprovideraccesstoken— owner-authenticated; returns a short-liveddrive.fileaccess token to the browser for Picker use (nothing else). Minted viaresolve-tokenfrom the stored refresh token.gdriveProvider.createDataContainer— creates the experiment folder under a suppliedparentId; unchangedMy Drive/DataPipefallback when absent.createExperiment— plumbs optionalparentFolderIdthrough.Front-end (
3e0a773)lib/google-picker.js— isolated, memoized, SSR-guarded gapi/Picker loader;pickDriveFolder()→{ id, name } | null. Folder-only view,setAppIdso thedrive.filegrant ties to our app.pages/admin/new.js(gdrive path only) — "Choose Drive folder" button → fetches token → opens Picker → passes selection into creation.createProviderExperimentforwardsparentFolderId.NEXT_PUBLIC_GOOGLE_PICKER_API_KEY(referrer/API-restricted, browser-safe) +NEXT_PUBLIC_GDRIVE_PROJECT_NUMBER.Additive / backward-compatible
parentFolderIdis optional everywhere; existing OSF and default-folder flows are untouched.Cloud setup already done (datapipe-test)
Drive API + Picker API enabled; restricted browser API key created; env vars wired.
Tests
Backend: full auth/validation matrix on the endpoint + parent-placement + default-path regression (emulator). Front-end:
parentFolderIdforwarding/omission, Picker single-injection + PICKED/CANCEL. Verified green (backend 36/36, front-end 11/11), clean builds.Session data is written server-side. That only works if the Picker's
drive.filegrant lets a later server token (same OAuth client) write into the picked folder. Folder creation will work regardless; the real check is: create an experiment in a picked folder, submit a real data session, and confirm the file lands in a subfolder of that folder. If the session write 403s, the grant assumption needs revisiting.🤖 Generated with Claude Code