feat(import): implement X OAuth 2.0 backend for live bookmark import#54
Open
davidorban wants to merge 1 commit intoviperrcrypto:mainfrom
Open
feat(import): implement X OAuth 2.0 backend for live bookmark import#54davidorban wants to merge 1 commit intoviperrcrypto:mainfrom
davidorban wants to merge 1 commit intoviperrcrypto:mainfrom
Conversation
Closes viperrcrypto#50 The Live Import tab in the UI already had the full X OAuth 2.0 flow wired up on the frontend, but all five backend API routes were missing, causing the tab to display 'X OAuth not configured' and 'Could not connect to the server' for every user. This PR implements the missing backend: ## New routes - GET /api/import/x-oauth/status Returns { configured, connected, tokenExpired, user } so the UI can render the correct state. - GET /api/import/x-oauth/authorize Generates a PKCE code_verifier + code_challenge, stores the verifier keyed by a random state value, and returns the X OAuth 2.0 authorization URL for the client to redirect to. - GET /api/import/x-oauth/callback Exchanges the auth code + PKCE verifier for access/refresh tokens, fetches the authenticated user via /2/users/me, stores everything in the Setting table, then redirects to /import?x_connected=true. - POST /api/import/x-oauth/disconnect Removes all stored X OAuth tokens from the database. - POST /api/import/x-oauth/fetch Fetches bookmarks via the X API v2 /2/users/:id/bookmarks endpoint with full pagination support (up to 50 pages). Automatically refreshes an expired access token using the stored refresh token. Supports both photo and video/GIF media via media_keys expansion. ## Configuration Add `APP_URL` to your environment to override the callback URL base (defaults to `http://localhost:3000`). Useful when running behind a reverse proxy or on a custom port. ## Notes - Supports both public clients (PKCE only) and confidential clients (PKCE + Basic auth with client_id:client_secret) — autodetected from whether a Client Secret is configured in Settings. - PKCE verifiers are stored ephemerally in the Setting table and cleaned up immediately after the callback completes. - Token refresh is handled transparently in the fetch route. Co-Authored-By: Oz <oz-agent@warp.dev>
|
Just a suggestion because I tried the same on my own local development side. The API costs are related per each item read (not per page received), so if you read a pagination of 100 elements, you will pay per 100 elementes either you already have them or not. For me, the right approach is getting 5 elements per page, so when one of the elements is already exported in a previous session, the deprecation cost will be 1 to 4 instead of 1 to 99. |
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.
Closes #50
The Live Import tab already has the complete X OAuth 2.0 UI, but all five backend routes were missing — causing every user to see:
This PR implements the missing backend.
New routes
/api/import/x-oauth/status{ configured, connected, tokenExpired, user }/api/import/x-oauth/authorize/api/import/x-oauth/callback/api/import/x-oauth/disconnect/api/import/x-oauth/fetchNotes
Settingtable and cleaned up after the callbackAPP_URLenv var to override the callback base URL (defaults tohttp://localhost:3000) — useful for reverse proxies or custom ports.env.exampleupdated withAPP_URLdocumentationTesting
Tested end-to-end with a live X Developer account: connected, fetched 900+ bookmarks with pagination, disconnected, and reconnected.