diff --git a/package-lock.json b/package-lock.json index fd3702d..bd0686f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@vectorize-io/vectorize-connect", - "version": "0.3.6", + "version": "0.3.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@vectorize-io/vectorize-connect", - "version": "0.3.6", + "version": "0.3.7", "license": "MIT", "devDependencies": { "@types/node": "^20.0.0", diff --git a/package.json b/package.json index 1cf6ff9..8d5274b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vectorize-io/vectorize-connect", - "version": "0.3.7", + "version": "0.3.8", "description": "A simple package for Google Drive authorization and file selection", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/src/baseOAuth/core/oauth.ts b/src/baseOAuth/core/oauth.ts index a300df8..1bb2393 100644 --- a/src/baseOAuth/core/oauth.ts +++ b/src/baseOAuth/core/oauth.ts @@ -160,12 +160,14 @@ export abstract class BaseOAuth { * @param code Authorization code from the OAuth redirect * @param config The OAuth configuration * @param error Optional error from the OAuth process + * @param nonce Optional nonce for Content Security Policy * @returns A Response object with the callback page */ public static createCallbackResponse( code: string, config: OAuthConfig, - error?: string | OAuthError + error?: string | OAuthError, + nonce?: string ): Promise { throw new Error('Method not implemented'); } diff --git a/src/baseOAuth/ui/picker.ts b/src/baseOAuth/ui/picker.ts index 6337ac3..f21e665 100644 --- a/src/baseOAuth/ui/picker.ts +++ b/src/baseOAuth/ui/picker.ts @@ -8,18 +8,20 @@ export abstract class BasePicker { /** * Abstract method to create HTML template for the picker page * Must be implemented by subclasses for connector-specific picker UI - * + * * @param tokens OAuth tokens for API access * @param config Configuration with necessary credentials * @param refreshToken Refresh token to include in selection data * @param preSelectedFiles Optional map of files to initialize as selected + * @param nonce Optional nonce for Content Security Policy * @returns HTML string for the picker interface */ abstract createPickerHTML( - tokens: OAuthResponse, - config: OAuthConfig, - refreshToken: string, - preSelectedFiles?: Record + tokens: OAuthResponse, + config: OAuthConfig, + refreshToken: string, + preSelectedFiles?: Record, + nonce?: string ): string; /** @@ -200,12 +202,13 @@ export abstract class BasePicker { /** * Utility method to generate the base HTML structure - * + * * @param title Page title * @param styles Additional CSS styles to include * @param head Additional head content (scripts, meta tags) * @param body Body content * @param scripts JavaScript to include at the end of body + * @param nonce Optional nonce for Content Security Policy * @returns Complete HTML string */ protected generateHTMLTemplate( @@ -213,7 +216,8 @@ export abstract class BasePicker { styles: string = '', head: string = '', body: string, - scripts: string + scripts: string, + nonce?: string ): string { return ` @@ -283,7 +287,7 @@ export abstract class BasePicker { ${body} - diff --git a/src/dropBoxOAuth/core/oauth.ts b/src/dropBoxOAuth/core/oauth.ts index 82e807e..4ef58be 100644 --- a/src/dropBoxOAuth/core/oauth.ts +++ b/src/dropBoxOAuth/core/oauth.ts @@ -86,12 +86,14 @@ export class DropboxOAuth extends BaseOAuth { * @param code Authorization code from the OAuth redirect * @param config The OAuth configuration * @param error Optional error from the OAuth process + * @param nonce Optional nonce for Content Security Policy * @returns A Response object with the callback page */ public static override async createCallbackResponse( code: string, config: DropboxOAuthConfig, - error?: string | OAuthError + error?: string | OAuthError, + nonce?: string ): Promise { if (error) { const errorObj = typeof error === 'string' ? new OAuthError(error, 'CALLBACK_ERROR') : error; @@ -107,8 +109,8 @@ export class DropboxOAuth extends BaseOAuth { ); // Use the Dropbox picker template - const htmlContent = DropboxPicker.createPickerHTML(tokens, config, tokens.refresh_token); - + const htmlContent = DropboxPicker.createPickerHTML(tokens, config, tokens.refresh_token, undefined, nonce); + return new Response(htmlContent, { headers: { 'Content-Type': 'text/html' } }); } catch (error) { return this.createErrorResponse( diff --git a/src/dropBoxOAuth/ui/picker.ts b/src/dropBoxOAuth/ui/picker.ts index e5ff4a3..233e93c 100644 --- a/src/dropBoxOAuth/ui/picker.ts +++ b/src/dropBoxOAuth/ui/picker.ts @@ -8,18 +8,20 @@ import { BasePicker } from '../../baseOAuth/ui/picker'; export class DropboxPicker extends BasePicker { /** * Creates an HTML template specifically for the Dropbox picker - * + * * @param tokens OAuth tokens for API access * @param config Dropbox specific configuration * @param refreshToken Refresh token to include in selection data * @param preSelectedFiles Optional map of files to initialize as selected + * @param nonce Optional nonce for Content Security Policy * @returns HTML string for the Dropbox picker interface */ createPickerHTML( - tokens: OAuthResponse, - config: DropboxOAuthConfig, - refreshToken: string, - preSelectedFiles?: Record + tokens: OAuthResponse, + config: DropboxOAuthConfig, + refreshToken: string, + preSelectedFiles?: Record, + nonce?: string ): string { const ui = this.getCommonUIElements(); @@ -217,7 +219,8 @@ export class DropboxPicker extends BasePicker { ${ui.fileListContainer} ${ui.submitButtonContainer} `, - dropboxScripts + dropboxScripts, + nonce ); } @@ -225,12 +228,13 @@ export class DropboxPicker extends BasePicker { * Create a static instance for backward compatibility */ static createPickerHTML( - tokens: OAuthResponse, - config: DropboxOAuthConfig, - refreshToken: string, - preSelectedFiles?: Record + tokens: OAuthResponse, + config: DropboxOAuthConfig, + refreshToken: string, + preSelectedFiles?: Record, + nonce?: string ): string { const picker = new DropboxPicker(); - return picker.createPickerHTML(tokens, config, refreshToken, preSelectedFiles); + return picker.createPickerHTML(tokens, config, refreshToken, preSelectedFiles, nonce); } } \ No newline at end of file diff --git a/src/googleDriveOAuth/core/oauth.ts b/src/googleDriveOAuth/core/oauth.ts index 8a0064b..04a55ef 100644 --- a/src/googleDriveOAuth/core/oauth.ts +++ b/src/googleDriveOAuth/core/oauth.ts @@ -91,12 +91,14 @@ export class GoogleDriveOAuth extends BaseOAuth { * @param code Authorization code from the OAuth redirect * @param config The OAuth configuration * @param error Optional error from the OAuth process + * @param nonce Optional nonce for Content Security Policy * @returns A Response object with the callback page */ public static override async createCallbackResponse( code: string, config: GoogleDriveOAuthConfig, - error?: string | OAuthError + error?: string | OAuthError, + nonce?: string ): Promise { if (error) { const errorObj = typeof error === 'string' ? new OAuthError(error, 'CALLBACK_ERROR') : error; @@ -112,8 +114,8 @@ export class GoogleDriveOAuth extends BaseOAuth { ); // Use the Google Drive picker template - const htmlContent = GoogleDrivePicker.createPickerHTML(tokens, config, tokens.refresh_token); - + const htmlContent = GoogleDrivePicker.createPickerHTML(tokens, config, tokens.refresh_token, undefined, nonce); + return new Response(htmlContent, { headers: { 'Content-Type': 'text/html' } }); } catch (error) { return this.createErrorResponse( diff --git a/src/googleDriveOAuth/ui/picker.ts b/src/googleDriveOAuth/ui/picker.ts index 36e2986..c24cac6 100644 --- a/src/googleDriveOAuth/ui/picker.ts +++ b/src/googleDriveOAuth/ui/picker.ts @@ -8,18 +8,20 @@ import { BasePicker } from '../../baseOAuth/ui/picker'; export class GoogleDrivePicker extends BasePicker { /** * Creates an HTML template specifically for the Google Drive picker - * + * * @param tokens OAuth tokens for API access * @param config Google Drive specific configuration * @param refreshToken Refresh token to include in selection data * @param preSelectedFiles Optional map of files to initialize as selected + * @param nonce Optional nonce for Content Security Policy * @returns HTML string for the Google Drive picker interface */ createPickerHTML( - tokens: OAuthResponse, - config: GoogleDriveOAuthConfig, - refreshToken: string, - preSelectedFiles?: Record + tokens: OAuthResponse, + config: GoogleDriveOAuthConfig, + refreshToken: string, + preSelectedFiles?: Record, + nonce?: string ): string { const ui = this.getCommonUIElements(); @@ -155,7 +157,8 @@ export class GoogleDrivePicker extends BasePicker { ${ui.fileListContainer} ${ui.submitButtonContainer} `, - googleDriveScripts + googleDriveScripts, + nonce ); } @@ -163,12 +166,13 @@ export class GoogleDrivePicker extends BasePicker { * Create a static instance for backward compatibility */ static createPickerHTML( - tokens: OAuthResponse, - config: GoogleDriveOAuthConfig, - refreshToken: string, - preSelectedFiles?: Record + tokens: OAuthResponse, + config: GoogleDriveOAuthConfig, + refreshToken: string, + preSelectedFiles?: Record, + nonce?: string ): string { const picker = new GoogleDrivePicker(); - return picker.createPickerHTML(tokens, config, refreshToken, preSelectedFiles); + return picker.createPickerHTML(tokens, config, refreshToken, preSelectedFiles, nonce); } } \ No newline at end of file diff --git a/src/notionOAuth/ui/picker.ts b/src/notionOAuth/ui/picker.ts index 9101867..3893bb8 100644 --- a/src/notionOAuth/ui/picker.ts +++ b/src/notionOAuth/ui/picker.ts @@ -8,18 +8,20 @@ import { NotionOAuthConfig } from '../types'; export class NotionPicker { /** * Creates the HTML content for the Notion picker UI - * + * * @param tokens The OAuth tokens received from Notion * @param config The OAuth configuration * @param accessToken The Notion access token to use for API calls * @param existingSelection Optional record of already selected pages + * @param nonce Optional nonce for Content Security Policy * @returns HTML string for the picker UI */ public static createPickerHTML( tokens: any, config: NotionOAuthConfig, accessToken: string, - existingSelection?: Record + existingSelection?: Record, + nonce?: string ): string { // Convert existing selection to JSON string for embedding in the HTML const existingSelectionStr = existingSelection @@ -411,8 +413,8 @@ export class NotionPicker { - -