-
Notifications
You must be signed in to change notification settings - Fork 3.2k
improvement(vault): new error throw and improvement #2734
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -159,6 +159,90 @@ Return ONLY the hold name - no explanations, no quotes, no extra text.`, | |||||||||||||||||||||||||||||||||||
| placeholder: 'Org Unit ID (alternative to emails)', | ||||||||||||||||||||||||||||||||||||
| condition: { field: 'operation', value: ['create_matters_holds', 'create_matters_export'] }, | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| // Date filtering for exports and holds (holds only support MAIL and GROUPS corpus) | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| id: 'startTime', | ||||||||||||||||||||||||||||||||||||
| title: 'Start Time', | ||||||||||||||||||||||||||||||||||||
| type: 'short-input', | ||||||||||||||||||||||||||||||||||||
| placeholder: 'YYYY-MM-DDTHH:mm:ssZ', | ||||||||||||||||||||||||||||||||||||
| condition: { field: 'operation', value: ['create_matters_export', 'create_matters_holds'] }, | ||||||||||||||||||||||||||||||||||||
| wandConfig: { | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+162
to
+169
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Date filtering fields show for all corpus types, but the comment states "holds only support MAIL and GROUPS corpus" for date filtering. Consider adding corpus-based conditions:
Suggested change
Or if holds truly need corpus restriction, the condition should be more complex to check corpus for holds operations. |
||||||||||||||||||||||||||||||||||||
| enabled: true, | ||||||||||||||||||||||||||||||||||||
| prompt: `Generate an ISO 8601 timestamp in GMT based on the user's description for Google Vault date filtering. | ||||||||||||||||||||||||||||||||||||
| The timestamp should be in the format: YYYY-MM-DDTHH:mm:ssZ (UTC timezone). | ||||||||||||||||||||||||||||||||||||
| Note: Google Vault rounds times to 12 AM on the specified date. | ||||||||||||||||||||||||||||||||||||
| Examples: | ||||||||||||||||||||||||||||||||||||
| - "yesterday" -> Calculate yesterday's date at 00:00:00Z | ||||||||||||||||||||||||||||||||||||
| - "last week" -> Calculate 7 days ago at 00:00:00Z | ||||||||||||||||||||||||||||||||||||
| - "beginning of this month" -> Calculate the 1st of current month at 00:00:00Z | ||||||||||||||||||||||||||||||||||||
| - "January 1, 2024" -> 2024-01-01T00:00:00Z | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Return ONLY the timestamp string - no explanations, no quotes, no extra text.`, | ||||||||||||||||||||||||||||||||||||
| placeholder: 'Describe the start date (e.g., "last month", "January 1, 2024")...', | ||||||||||||||||||||||||||||||||||||
| generationType: 'timestamp', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| id: 'endTime', | ||||||||||||||||||||||||||||||||||||
| title: 'End Time', | ||||||||||||||||||||||||||||||||||||
| type: 'short-input', | ||||||||||||||||||||||||||||||||||||
| placeholder: 'YYYY-MM-DDTHH:mm:ssZ', | ||||||||||||||||||||||||||||||||||||
| condition: { field: 'operation', value: ['create_matters_export', 'create_matters_holds'] }, | ||||||||||||||||||||||||||||||||||||
| wandConfig: { | ||||||||||||||||||||||||||||||||||||
| enabled: true, | ||||||||||||||||||||||||||||||||||||
| prompt: `Generate an ISO 8601 timestamp in GMT based on the user's description for Google Vault date filtering. | ||||||||||||||||||||||||||||||||||||
| The timestamp should be in the format: YYYY-MM-DDTHH:mm:ssZ (UTC timezone). | ||||||||||||||||||||||||||||||||||||
| Note: Google Vault rounds times to 12 AM on the specified date. | ||||||||||||||||||||||||||||||||||||
| Examples: | ||||||||||||||||||||||||||||||||||||
| - "now" -> Current timestamp | ||||||||||||||||||||||||||||||||||||
| - "today" -> Today's date at 23:59:59Z | ||||||||||||||||||||||||||||||||||||
| - "end of last month" -> Last day of previous month at 23:59:59Z | ||||||||||||||||||||||||||||||||||||
| - "December 31, 2024" -> 2024-12-31T23:59:59Z | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Return ONLY the timestamp string - no explanations, no quotes, no extra text.`, | ||||||||||||||||||||||||||||||||||||
| placeholder: 'Describe the end date (e.g., "today", "end of last quarter")...', | ||||||||||||||||||||||||||||||||||||
| generationType: 'timestamp', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| id: 'terms', | ||||||||||||||||||||||||||||||||||||
| title: 'Search Terms', | ||||||||||||||||||||||||||||||||||||
| type: 'long-input', | ||||||||||||||||||||||||||||||||||||
| placeholder: 'Enter search query (e.g., from:[email protected] subject:confidential)', | ||||||||||||||||||||||||||||||||||||
| condition: { field: 'operation', value: ['create_matters_export', 'create_matters_holds'] }, | ||||||||||||||||||||||||||||||||||||
| wandConfig: { | ||||||||||||||||||||||||||||||||||||
| enabled: true, | ||||||||||||||||||||||||||||||||||||
| prompt: `Generate a Google Vault search query based on the user's description. | ||||||||||||||||||||||||||||||||||||
| The query can use Gmail-style search operators for MAIL corpus: | ||||||||||||||||||||||||||||||||||||
| - from:[email protected] - emails from specific sender | ||||||||||||||||||||||||||||||||||||
| - to:[email protected] - emails to specific recipient | ||||||||||||||||||||||||||||||||||||
| - subject:keyword - emails with keyword in subject | ||||||||||||||||||||||||||||||||||||
| - has:attachment - emails with attachments | ||||||||||||||||||||||||||||||||||||
| - filename:pdf - emails with PDF attachments | ||||||||||||||||||||||||||||||||||||
| - before:YYYY/MM/DD - emails before date | ||||||||||||||||||||||||||||||||||||
| - after:YYYY/MM/DD - emails after date | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| For DRIVE corpus, use Drive search operators: | ||||||||||||||||||||||||||||||||||||
| - owner:[email protected] - files owned by user | ||||||||||||||||||||||||||||||||||||
| - type:document - specific file types | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| For holds, date filtering only works with MAIL and GROUPS corpus. | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Return ONLY the search query - no explanations, no quotes, no extra text.`, | ||||||||||||||||||||||||||||||||||||
| placeholder: 'Describe what content to search for...', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| // Drive-specific option for holds | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| id: 'includeSharedDrives', | ||||||||||||||||||||||||||||||||||||
| title: 'Include Shared Drives', | ||||||||||||||||||||||||||||||||||||
| type: 'switch', | ||||||||||||||||||||||||||||||||||||
| condition: { | ||||||||||||||||||||||||||||||||||||
| field: 'operation', | ||||||||||||||||||||||||||||||||||||
| value: 'create_matters_holds', | ||||||||||||||||||||||||||||||||||||
| and: { field: 'corpus', value: 'DRIVE' }, | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| id: 'exportId', | ||||||||||||||||||||||||||||||||||||
| title: 'Export ID', | ||||||||||||||||||||||||||||||||||||
|
|
@@ -296,9 +380,16 @@ Return ONLY the description text - no explanations, no quotes, no extra text.`, | |||||||||||||||||||||||||||||||||||
| corpus: { type: 'string', description: 'Data corpus (MAIL, DRIVE, GROUPS, etc.)' }, | ||||||||||||||||||||||||||||||||||||
| accountEmails: { type: 'string', description: 'Comma-separated account emails' }, | ||||||||||||||||||||||||||||||||||||
| orgUnitId: { type: 'string', description: 'Organization unit ID' }, | ||||||||||||||||||||||||||||||||||||
| startTime: { type: 'string', description: 'Start time for date filtering (ISO 8601 format)' }, | ||||||||||||||||||||||||||||||||||||
| endTime: { type: 'string', description: 'End time for date filtering (ISO 8601 format)' }, | ||||||||||||||||||||||||||||||||||||
| terms: { type: 'string', description: 'Search query terms' }, | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Create hold inputs | ||||||||||||||||||||||||||||||||||||
| holdName: { type: 'string', description: 'Name for the hold' }, | ||||||||||||||||||||||||||||||||||||
| includeSharedDrives: { | ||||||||||||||||||||||||||||||||||||
| type: 'boolean', | ||||||||||||||||||||||||||||||||||||
| description: 'Include files in shared drives (for DRIVE corpus holds)', | ||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // Download export file inputs | ||||||||||||||||||||||||||||||||||||
| bucketName: { type: 'string', description: 'GCS bucket name from export' }, | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1149,7 +1149,7 @@ | |||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| throw new Error(`Unknown OAuth provider: ${providerId}`) | ||||||||||||||||||||
|
Check failure on line 1152 in apps/sim/lib/oauth/oauth.ts
|
||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| export async function refreshOAuthToken( | ||||||||||||||||||||
|
|
@@ -1171,7 +1171,7 @@ | |||||||||||||||||||
|
|
||||||||||||||||||||
| if (!response.ok) { | ||||||||||||||||||||
| const errorText = await response.text() | ||||||||||||||||||||
| let errorData = errorText | ||||||||||||||||||||
| let errorData: any = errorText | ||||||||||||||||||||
|
|
||||||||||||||||||||
| try { | ||||||||||||||||||||
| errorData = JSON.parse(errorText) | ||||||||||||||||||||
|
|
@@ -1191,7 +1191,30 @@ | |||||||||||||||||||
| hasRefreshToken: !!refreshToken, | ||||||||||||||||||||
| refreshTokenPrefix: refreshToken ? `${refreshToken.substring(0, 10)}...` : 'none', | ||||||||||||||||||||
| }) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Check for Google Workspace session control errors (RAPT - Reauthentication Policy Token) | ||||||||||||||||||||
| // This occurs when the organization enforces periodic re-authentication | ||||||||||||||||||||
| if ( | ||||||||||||||||||||
| typeof errorData === 'object' && | ||||||||||||||||||||
| (errorData.error_subtype === 'invalid_rapt' || | ||||||||||||||||||||
| errorData.error_description?.includes('reauth related error')) | ||||||||||||||||||||
|
Comment on lines
+1197
to
+1200
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
| ) { | ||||||||||||||||||||
| throw new Error( | ||||||||||||||||||||
| `Session expired due to organization security policy. Please reconnect your ${providerId} account to continue. Alternatively, ask your Google Workspace admin to exempt this app from session control: Admin Console → Security → Google Cloud session control → "Exempt trusted apps".` | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| if ( | ||||||||||||||||||||
| typeof errorData === 'object' && | ||||||||||||||||||||
| errorData.error === 'invalid_grant' && | ||||||||||||||||||||
| !errorData.error_subtype | ||||||||||||||||||||
|
Comment on lines
+1207
to
+1210
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
| ) { | ||||||||||||||||||||
| throw new Error( | ||||||||||||||||||||
| `Access has been revoked or the refresh token is no longer valid. Please reconnect your ${providerId} account.` | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| throw new Error(`Failed to refresh token: ${response.status} ${errorText}`) | ||||||||||||||||||||
|
Check failure on line 1217 in apps/sim/lib/oauth/oauth.ts
|
||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| const data = await response.json() | ||||||||||||||||||||
|
|
@@ -1224,6 +1247,8 @@ | |||||||||||||||||||
| } | ||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||
| logger.error('Error refreshing token:', { error }) | ||||||||||||||||||||
| return null | ||||||||||||||||||||
| // Re-throw specific errors so they propagate with their detailed messages | ||||||||||||||||||||
| // Only return null for truly unexpected errors without useful messages | ||||||||||||||||||||
| throw error | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
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.
Changing
return nulltothrow errorbreaks backward compatibility. Many callers expectrefreshAccessTokenIfNeededto returnnullon failure and checkif (!accessToken). This change will cause unhandled exceptions in:apps/sim/lib/webhooks/utils.server.ts:2129,2816,2902apps/sim/lib/webhooks/provider-subscriptions.ts:57,190apps/sim/app/api/tools/gmail/labels/route.ts:70apps/sim/app/api/tools/sharepoint/sites/route.ts:53Either revert to returning
null, or wrap all callers in try-catch blocks.