From 8c1175225fe3279ba49b35e675e748778f262230 Mon Sep 17 00:00:00 2001 From: Kushal Bhana <68599557+kushalbhana@users.noreply.github.com> Date: Wed, 1 Oct 2025 15:21:09 +0530 Subject: [PATCH 1/4] Google Calendar Tool Missing sendUpdates Parameter (#5241) * Google Calendar Tool Missing sendUpdates Parameter * option in Tools and NOT default to send all --- .../tools/GoogleCalendar/GoogleCalendar.ts | 18 +++++++++++++++++- .../nodes/tools/GoogleCalendar/core.ts | 13 +++++++++++-- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/components/nodes/tools/GoogleCalendar/GoogleCalendar.ts b/packages/components/nodes/tools/GoogleCalendar/GoogleCalendar.ts index 38a0a6291..7498a1957 100644 --- a/packages/components/nodes/tools/GoogleCalendar/GoogleCalendar.ts +++ b/packages/components/nodes/tools/GoogleCalendar/GoogleCalendar.ts @@ -272,6 +272,22 @@ class GoogleCalendar_Tools implements INode { additionalParams: true, optional: true }, + { + label: 'Send Updates to', + name: 'sendUpdates', + type: 'options', + description: 'Send Updates to attendees', + options: [ + { label: 'All', name: 'all' }, + { label: 'External Only', name: 'externalOnly' }, + { label: 'None', name: 'none' } + ], + show: { + eventActions: ['createEvent', 'updateEvent'] + }, + additionalParams: true, + optional: true + }, { label: 'Recurrence Rules', name: 'recurrence', @@ -560,7 +576,6 @@ class GoogleCalendar_Tools implements INode { } const defaultParams = this.transformNodeInputsToToolArgs(nodeData) - const tools = createGoogleCalendarTools({ accessToken, actions, @@ -587,6 +602,7 @@ class GoogleCalendar_Tools implements INode { if (nodeData.inputs?.startDate) defaultParams.startDate = nodeData.inputs.startDate if (nodeData.inputs?.endDate) defaultParams.endDate = nodeData.inputs.endDate if (nodeData.inputs?.attendees) defaultParams.attendees = nodeData.inputs.attendees + if (nodeData.inputs?.sendUpdates) defaultParams.sendUpdates = nodeData.inputs.sendUpdates if (nodeData.inputs?.recurrence) defaultParams.recurrence = nodeData.inputs.recurrence if (nodeData.inputs?.reminderMinutes) defaultParams.reminderMinutes = nodeData.inputs.reminderMinutes if (nodeData.inputs?.visibility) defaultParams.visibility = nodeData.inputs.visibility diff --git a/packages/components/nodes/tools/GoogleCalendar/core.ts b/packages/components/nodes/tools/GoogleCalendar/core.ts index b613d0d1f..00f21d85d 100644 --- a/packages/components/nodes/tools/GoogleCalendar/core.ts +++ b/packages/components/nodes/tools/GoogleCalendar/core.ts @@ -48,6 +48,7 @@ const CreateEventSchema = z.object({ endDate: z.string().optional().describe('End date for all-day events (YYYY-MM-DD)'), timeZone: z.string().optional().describe('Time zone (e.g., America/New_York)'), attendees: z.string().optional().describe('Comma-separated list of attendee emails'), + sendUpdates: z.enum(['all', 'externalOnly', 'none']).optional().default('all').describe('Whether to send notifications to attendees'), recurrence: z.string().optional().describe('Recurrence rules (RRULE format)'), reminderMinutes: z.number().optional().describe('Minutes before event to send reminder'), visibility: z.enum(['default', 'public', 'private', 'confidential']).optional().describe('Event visibility') @@ -70,6 +71,7 @@ const UpdateEventSchema = z.object({ endDate: z.string().optional().describe('Updated end date for all-day events (YYYY-MM-DD)'), timeZone: z.string().optional().describe('Updated time zone'), attendees: z.string().optional().describe('Updated comma-separated list of attendee emails'), + sendUpdates: z.enum(['all', 'externalOnly', 'none']).optional().default('all').describe('Whether to send notifications to attendees'), recurrence: z.string().optional().describe('Updated recurrence rules'), reminderMinutes: z.number().optional().describe('Updated reminder minutes'), visibility: z.enum(['default', 'public', 'private', 'confidential']).optional().describe('Updated event visibility') @@ -286,8 +288,11 @@ class CreateEventTool extends BaseGoogleCalendarTool { } if (params.visibility) eventData.visibility = params.visibility + const queryParams = new URLSearchParams() + if (params.sendUpdates) queryParams.append('sendUpdates', params.sendUpdates) + + const endpoint = `calendars/${encodeURIComponent(params.calendarId)}/events?${queryParams.toString()}` - const endpoint = `calendars/${encodeURIComponent(params.calendarId)}/events` const response = await this.makeGoogleCalendarRequest({ endpoint, method: 'POST', body: eventData, params }) return response } catch (error) { @@ -395,8 +400,12 @@ class UpdateEventTool extends BaseGoogleCalendarTool { } if (params.visibility) updateData.visibility = params.visibility + const queryParams = new URLSearchParams() + if (params.sendUpdates) queryParams.append('sendUpdates', params.sendUpdates) - const endpoint = `calendars/${encodeURIComponent(params.calendarId)}/events/${encodeURIComponent(params.eventId)}` + const endpoint = `calendars/${encodeURIComponent(params.calendarId)}/events/${encodeURIComponent( + params.eventId + )}?${queryParams.toString()}` const response = await this.makeGoogleCalendarRequest({ endpoint, method: 'PUT', body: updateData, params }) return response } catch (error) { From a86f618186a163802c3a5732b3817d75d554b835 Mon Sep 17 00:00:00 2001 From: Henry Heng Date: Wed, 1 Oct 2025 11:54:07 +0100 Subject: [PATCH 2/4] Chore/Secure Cookies Env Variable (#5281) Enhanced cookie security handling in the passport middleware to allow explicit configuration of secure cookie settings. --- docker/.env.example | 1 + docker/docker-compose-queue-prebuilt.yml | 2 ++ docker/docker-compose.yml | 1 + docker/worker/.env.example | 1 + docker/worker/docker-compose.yml | 1 + packages/server/.env.example | 1 + .../src/enterprise/middleware/passport/index.ts | 11 ++++++++++- 7 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docker/.env.example b/docker/.env.example index b6cc050b0..dab25248a 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -99,6 +99,7 @@ JWT_TOKEN_EXPIRY_IN_MINUTES=360 JWT_REFRESH_TOKEN_EXPIRY_IN_MINUTES=43200 # EXPIRE_AUTH_TOKENS_ON_RESTART=true # (if you need to expire all tokens on app restart) # EXPRESS_SESSION_SECRET=flowise +# SECURE_COOKIES= # INVITE_TOKEN_EXPIRY_IN_HOURS=24 # PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS=15 diff --git a/docker/docker-compose-queue-prebuilt.yml b/docker/docker-compose-queue-prebuilt.yml index 51a18e96d..0063eeb1f 100644 --- a/docker/docker-compose-queue-prebuilt.yml +++ b/docker/docker-compose-queue-prebuilt.yml @@ -89,6 +89,7 @@ services: - PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS=${PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS} - PASSWORD_SALT_HASH_ROUNDS=${PASSWORD_SALT_HASH_ROUNDS} - TOKEN_HASH_SECRET=${TOKEN_HASH_SECRET} + - SECURE_COOKIES=${SECURE_COOKIES} # EMAIL - SMTP_HOST=${SMTP_HOST} @@ -232,6 +233,7 @@ services: - PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS=${PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS} - PASSWORD_SALT_HASH_ROUNDS=${PASSWORD_SALT_HASH_ROUNDS} - TOKEN_HASH_SECRET=${TOKEN_HASH_SECRET} + - SECURE_COOKIES=${SECURE_COOKIES} # EMAIL - SMTP_HOST=${SMTP_HOST} diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 54bcac359..f66d7106d 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -74,6 +74,7 @@ services: - PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS=${PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS} - PASSWORD_SALT_HASH_ROUNDS=${PASSWORD_SALT_HASH_ROUNDS} - TOKEN_HASH_SECRET=${TOKEN_HASH_SECRET} + - SECURE_COOKIES=${SECURE_COOKIES} # EMAIL - SMTP_HOST=${SMTP_HOST} diff --git a/docker/worker/.env.example b/docker/worker/.env.example index 6c2ce8c52..769286dff 100644 --- a/docker/worker/.env.example +++ b/docker/worker/.env.example @@ -99,6 +99,7 @@ JWT_TOKEN_EXPIRY_IN_MINUTES=360 JWT_REFRESH_TOKEN_EXPIRY_IN_MINUTES=43200 # EXPIRE_AUTH_TOKENS_ON_RESTART=true # (if you need to expire all tokens on app restart) # EXPRESS_SESSION_SECRET=flowise +# SECURE_COOKIES= # INVITE_TOKEN_EXPIRY_IN_HOURS=24 # PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS=15 diff --git a/docker/worker/docker-compose.yml b/docker/worker/docker-compose.yml index 71de912a7..952dc04cd 100644 --- a/docker/worker/docker-compose.yml +++ b/docker/worker/docker-compose.yml @@ -74,6 +74,7 @@ services: - PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS=${PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS} - PASSWORD_SALT_HASH_ROUNDS=${PASSWORD_SALT_HASH_ROUNDS} - TOKEN_HASH_SECRET=${TOKEN_HASH_SECRET} + - SECURE_COOKIES=${SECURE_COOKIES} # EMAIL - SMTP_HOST=${SMTP_HOST} diff --git a/packages/server/.env.example b/packages/server/.env.example index f8ba1c485..219a17d1d 100644 --- a/packages/server/.env.example +++ b/packages/server/.env.example @@ -99,6 +99,7 @@ JWT_TOKEN_EXPIRY_IN_MINUTES=360 JWT_REFRESH_TOKEN_EXPIRY_IN_MINUTES=43200 # EXPIRE_AUTH_TOKENS_ON_RESTART=true # (if you need to expire all tokens on app restart) # EXPRESS_SESSION_SECRET=flowise +# SECURE_COOKIES= # INVITE_TOKEN_EXPIRY_IN_HOURS=24 # PASSWORD_RESET_TOKEN_EXPIRY_IN_MINS=15 diff --git a/packages/server/src/enterprise/middleware/passport/index.ts b/packages/server/src/enterprise/middleware/passport/index.ts index 5cbf0b16b..8cb0f594a 100644 --- a/packages/server/src/enterprise/middleware/passport/index.ts +++ b/packages/server/src/enterprise/middleware/passport/index.ts @@ -33,7 +33,16 @@ const expireAuthTokensOnRestart = process.env.EXPIRE_AUTH_TOKENS_ON_RESTART === const jwtAuthTokenSecret = process.env.JWT_AUTH_TOKEN_SECRET || 'auth_token' const jwtRefreshSecret = process.env.JWT_REFRESH_TOKEN_SECRET || process.env.JWT_AUTH_TOKEN_SECRET || 'refresh_token' -const secureCookie = process.env.APP_URL?.startsWith('https') ? true : false +// Allow explicit override of cookie security settings +// This is useful when running behind a reverse proxy/load balancer that terminates SSL +const secureCookie = + process.env.SECURE_COOKIES === 'false' + ? false + : process.env.SECURE_COOKIES === 'true' + ? true + : process.env.APP_URL?.startsWith('https') + ? true + : false const jwtOptions = { secretOrKey: jwtAuthTokenSecret, audience: jwtAudience, From 580957e4aafd17fc89e81628f29b429731ad70f1 Mon Sep 17 00:00:00 2001 From: Henry Heng Date: Wed, 1 Oct 2025 12:32:30 +0100 Subject: [PATCH 3/4] Chore/Remove Previous Subscription (#5282) Remove cancel subscription functionality from account controller and UI components; update email background and logo URLs across multiple email templates. --- .../controllers/account.controller.ts | 25 ----- .../enterprise/emails/verify_email_cloud.hbs | 4 +- .../enterprise/emails/verify_email_cloud.html | 4 +- .../enterprise/emails/workspace_add_cloud.hbs | 4 +- .../emails/workspace_add_cloud.html | 4 +- .../emails/workspace_new_invite_cloud.hbs | 4 +- .../emails/workspace_new_invite_cloud.html | 4 +- .../workspace_new_invite_enterprise.hbs | 4 +- .../workspace_new_invite_enterprise.html | 4 +- .../emails/workspace_update_invite_cloud.hbs | 4 +- .../emails/workspace_update_invite_cloud.html | 4 +- .../workspace_update_invite_enterprise.hbs | 4 +- .../workspace_update_invite_enterprise.html | 4 +- .../emails/workspace_user_reset_password.hbs | 4 +- .../emails/workspace_user_reset_password.html | 4 +- .../src/enterprise/routes/account.route.ts | 2 - packages/ui/src/api/account.api.js | 2 - packages/ui/src/views/account/index.jsx | 104 ------------------ packages/ui/src/views/auth/signIn.jsx | 12 -- 19 files changed, 28 insertions(+), 173 deletions(-) diff --git a/packages/server/src/enterprise/controllers/account.controller.ts b/packages/server/src/enterprise/controllers/account.controller.ts index f29af60fc..9c360a6a9 100644 --- a/packages/server/src/enterprise/controllers/account.controller.ts +++ b/packages/server/src/enterprise/controllers/account.controller.ts @@ -2,7 +2,6 @@ import { Request, Response, NextFunction } from 'express' import { StatusCodes } from 'http-status-codes' import { AccountService } from '../services/account.service' import { getRunningExpressApp } from '../../utils/getRunningExpressApp' -import axios from 'axios' export class AccountController { public async register(req: Request, res: Response, next: NextFunction) { @@ -84,30 +83,6 @@ export class AccountController { } } - public async cancelPreviousCloudSubscrption(req: Request, res: Response, next: NextFunction) { - try { - const { email } = req.body - if (!email) { - return res.status(StatusCodes.BAD_REQUEST).json({ message: 'Email is required' }) - } - - const headers = { - 'Content-Type': 'application/json', - Accept: 'application/json' - } - - const response = await axios.post(`${process.env.ENGINE_URL}/cancel-subscription`, { email }, { headers }) - - if (response.status === 200) { - return res.status(StatusCodes.OK).json(response.data) - } else { - return res.status(response.status).json(response.data) - } - } catch (error) { - next(error) - } - } - public async logout(req: Request, res: Response, next: NextFunction) { try { if (req.user) { diff --git a/packages/server/src/enterprise/emails/verify_email_cloud.hbs b/packages/server/src/enterprise/emails/verify_email_cloud.hbs index 5d7bd2797..98b276e72 100644 --- a/packages/server/src/enterprise/emails/verify_email_cloud.hbs +++ b/packages/server/src/enterprise/emails/verify_email_cloud.hbs @@ -79,7 +79,7 @@ style=' position: relative; background-color: #151719 !important; - background-image: url(https://auth.flowiseai.com/storage/v1/object/public/flowise-static-assets/flowise_email_bg.svg); + background-image: url(https://general-flowise.s3.us-east-1.amazonaws.com/flowise_email_bg.svg); background-position: center top; background-size: contain; background-repeat: no-repeat; @@ -220,7 +220,7 @@