-
Notifications
You must be signed in to change notification settings - Fork 0
Integrate external services for data management #5
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
base: main
Are you sure you want to change the base?
Integrate external services for data management #5
Conversation
Co-authored-by: info <info@reeseastor.com>
|
Cursor Agent can help with this pull request. Just |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR transforms the workspace from a local SQLite-based application to a cloud-integrated platform using Supabase, Notion, and Google Drive. The migration introduces user authentication with JWT tokens, external service synchronization, and comprehensive cloud backup capabilities.
- Replaces SQLite with Supabase for cloud database and authentication
- Integrates Notion and Google Drive APIs for external data synchronization and backup
- Adds comprehensive user authentication system with profile management
Reviewed Changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| supabase/schema.sql | Defines complete PostgreSQL schema with RLS policies, custom types, and triggers |
| services/syncService.js | Implements synchronization logic between Supabase and external services |
| server.js | Updates server routes to use Supabase authentication and external integrations |
| public/styles.css | Adds modal styling and sync badge components for authentication UI |
| public/script.js | Updates frontend to use authenticated requests and display sync status |
| public/index.html | Adds authentication and profile management modals |
| public/auth.js | Implements client-side authentication and session management |
| package.json | Adds dependencies for Supabase, Notion, Google APIs, and authentication |
| middleware/auth.js | Provides JWT token validation middleware for protected routes |
| config/supabase.js | Configures Supabase client connections |
| config/notion.js | Implements Notion API integration helpers |
| config/googleDrive.js | Provides Google Drive API functionality for file operations |
| SETUP.md | Comprehensive setup guide for all cloud integrations |
| .env.example | Template for required environment variables |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| RETURNS TRIGGER AS $$ | ||
| BEGIN | ||
| INSERT INTO public.profiles (id, email, full_name) | ||
| VALUES (NEW.id, NEW.email, NEW.raw_user_meta_data->>'full_name'); |
Copilot
AI
Sep 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function assumes raw_user_meta_data contains a full_name key, but this could be null or missing, potentially causing insert failures. Consider adding a COALESCE or null check.
| VALUES (NEW.id, NEW.email, NEW.raw_user_meta_data->>'full_name'); | |
| VALUES (NEW.id, NEW.email, COALESCE(NEW.raw_user_meta_data->>'full_name', '')); |
| try { | ||
| await this.logSync(userId, 'company', companyData.id, 'notion', action, 'pending'); | ||
|
|
||
| const notionResult = await notionHelpers.createCompany(companyData.name, companyData.industry); |
Copilot
AI
Sep 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the Notion API call fails, the error message from the catch block may not be user-friendly. Consider wrapping API errors with more descriptive messages for better user experience.
| const fileMetadata = { | ||
| name: fileName, | ||
| parents: folderId ? [folderId] : [process.env.GOOGLE_DRIVE_FOLDER_ID] |
Copilot
AI
Sep 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If process.env.GOOGLE_DRIVE_FOLDER_ID is undefined, this will create an array with undefined, potentially causing Google Drive API errors. Add validation to ensure the environment variable is set.
| const fileMetadata = { | |
| name: fileName, | |
| parents: folderId ? [folderId] : [process.env.GOOGLE_DRIVE_FOLDER_ID] | |
| // Validate folderId or environment variable | |
| const resolvedFolderId = folderId || process.env.GOOGLE_DRIVE_FOLDER_ID; | |
| if (!resolvedFolderId) { | |
| throw new Error('No Google Drive folder ID provided. Please specify a folderId or set the GOOGLE_DRIVE_FOLDER_ID environment variable.'); | |
| } | |
| const fileMetadata = { | |
| name: fileName, | |
| parents: [resolvedFolderId] |
| clearInterval(checkAuth); | ||
| showSuccess('Google Drive connected successfully!'); | ||
| updateIntegrationStatus(); | ||
| } else if (window.location.search.includes('google_auth=error')) { | ||
| clearInterval(checkAuth); | ||
| showError('Google Drive connection failed'); | ||
| } | ||
| }, 1000); |
Copilot
AI
Sep 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This polling mechanism will run indefinitely if the user closes the auth popup without completing authentication, causing a memory leak. Add a timeout to clear the interval after a reasonable duration.
| clearInterval(checkAuth); | |
| showSuccess('Google Drive connected successfully!'); | |
| updateIntegrationStatus(); | |
| } else if (window.location.search.includes('google_auth=error')) { | |
| clearInterval(checkAuth); | |
| showError('Google Drive connection failed'); | |
| } | |
| }, 1000); | |
| clearInterval(checkAuth); | |
| clearTimeout(authTimeout); | |
| showSuccess('Google Drive connected successfully!'); | |
| updateIntegrationStatus(); | |
| } else if (window.location.search.includes('google_auth=error')) { | |
| clearInterval(checkAuth); | |
| clearTimeout(authTimeout); | |
| showError('Google Drive connection failed'); | |
| } | |
| }, 1000); | |
| // Add a timeout to clear the interval after 60 seconds | |
| const authTimeout = setTimeout(() => { | |
| clearInterval(checkAuth); | |
| showError('Google Drive authentication timed out. Please try again.'); | |
| }, 60000); |
| const uploadedFile = await this.uploadFile(tempFilePath, fileName, mimeType, novelsFolderId); | ||
|
|
||
| // Clean up temp file | ||
| fs.unlinkSync(tempFilePath); |
Copilot
AI
Sep 29, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the file upload fails or an exception occurs before this line, the temporary file may not be cleaned up, leading to disk space accumulation. Use try-finally or ensure cleanup happens in all code paths.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
| app.get('/auth/google/callback', authenticateToken, async (req, res) => { | ||
| try { | ||
| const { code } = req.query; | ||
| const tokens = await googleDriveHelpers.getTokens(code); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P1] Allow OAuth callback without bearer token
The Google OAuth redirect is wrapped in authenticateToken, but browser redirects from Google never carry the Authorization header you expect. Every /auth/google/callback request will therefore be rejected before the authorization code is exchanged and the tokens written to the profile, so users can never connect Google Drive. Consider identifying the user via an OAuth state parameter or removing the token requirement on this callback.
Useful? React with 👍 / 👎.
| } catch (error) { | ||
| res.status(400).json({ error: error.message }); | ||
| } | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Integrate Supabase, Notion, and Google Drive to transform the workspace into a cloud-integrated application.
This PR replaces the local SQLite database with Supabase for cloud storage and authentication, and adds Notion and Google Drive integrations for enhanced collaboration, document backup, and data synchronization across companies, novels, and credit memos.
Note
Migrates backend to Supabase with JWT auth and adds Notion + Google Drive integrations (OAuth, sync/backup), new sync endpoints, and auth/integration UI.
supabase/schema.sql), admin/client setup (config/supabase.js), and JWT auth middleware (middleware/auth.js); add/auth/*and profile endpoints.config/notion.js) and Google Drive (config/googleDrive.js, OAuth callback) with centralizedservices/syncService.js(create/update, backups, sync logs, status); new endpoints for sync status and manual sync.public/auth.js), integration status/connect; route calls viaauthenticatedFetch..env.example, detailedSETUP.md; install Supabase/Notion/Google APIs and supporting deps inpackage.json.Written by Cursor Bugbot for commit 8d1ab88. This will update automatically on new commits. Configure here.