Compare commits

...

5 Commits

Author SHA1 Message Date
Waleed Latif
243e01bb21 extracted duplicate code into helper for resolving user from jwt 2026-01-24 01:43:06 -08:00
Waleed Latif
28b51b7791 move session check higher in checkSessionOrInternalAuth 2026-01-24 01:39:01 -08:00
Waleed Latif
b1bcd9a796 updated agent handler 2026-01-24 01:22:02 -08:00
Waleed Latif
a45c019c7c test(security): update function execute tests for checkInternalAuth 2026-01-23 19:57:28 -08:00
Waleed Latif
f78659e56e fix(security): restrict API key access on internal-only routes 2026-01-23 19:44:21 -08:00
88 changed files with 575 additions and 758 deletions

View File

@@ -85,10 +85,10 @@ vi.mock('@/lib/execution/isolated-vm', () => ({
vi.mock('@sim/logger', () => loggerMock) vi.mock('@sim/logger', () => loggerMock)
vi.mock('@/lib/auth/hybrid', () => ({ vi.mock('@/lib/auth/hybrid', () => ({
checkHybridAuth: vi.fn().mockResolvedValue({ checkInternalAuth: vi.fn().mockResolvedValue({
success: true, success: true,
userId: 'user-123', userId: 'user-123',
authType: 'session', authType: 'internal_jwt',
}), }),
})) }))
@@ -119,8 +119,8 @@ describe('Function Execute API Route', () => {
describe('Security Tests', () => { describe('Security Tests', () => {
it('should reject unauthorized requests', async () => { it('should reject unauthorized requests', async () => {
const { checkHybridAuth } = await import('@/lib/auth/hybrid') const { checkInternalAuth } = await import('@/lib/auth/hybrid')
vi.mocked(checkHybridAuth).mockResolvedValueOnce({ vi.mocked(checkInternalAuth).mockResolvedValueOnce({
success: false, success: false,
error: 'Unauthorized', error: 'Unauthorized',
}) })

View File

@@ -1,6 +1,6 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { isE2bEnabled } from '@/lib/core/config/feature-flags' import { isE2bEnabled } from '@/lib/core/config/feature-flags'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { executeInE2B } from '@/lib/execution/e2b' import { executeInE2B } from '@/lib/execution/e2b'
@@ -582,7 +582,7 @@ export async function POST(req: NextRequest) {
let resolvedCode = '' // Store resolved code for error reporting let resolvedCode = '' // Store resolved code for error reporting
try { try {
const auth = await checkHybridAuth(req) const auth = await checkInternalAuth(req)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized function execution attempt`) logger.warn(`[${requestId}] Unauthorized function execution attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -3,7 +3,7 @@ import { account } from '@sim/db/schema'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { eq } from 'drizzle-orm' import { eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils' import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils'
import { refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils' import { refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils'
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const startTime = Date.now() const startTime = Date.now()
try { try {
const auth = await checkHybridAuth(request, { requireWorkflowId: false }) const auth = await checkInternalAuth(request, { requireWorkflowId: false })
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
} }

View File

@@ -181,7 +181,7 @@ describe('Custom Tools API Routes', () => {
})) }))
vi.doMock('@/lib/auth/hybrid', () => ({ vi.doMock('@/lib/auth/hybrid', () => ({
checkHybridAuth: vi.fn().mockResolvedValue({ checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
success: true, success: true,
userId: 'user-123', userId: 'user-123',
authType: 'session', authType: 'session',
@@ -254,7 +254,7 @@ describe('Custom Tools API Routes', () => {
) )
vi.doMock('@/lib/auth/hybrid', () => ({ vi.doMock('@/lib/auth/hybrid', () => ({
checkHybridAuth: vi.fn().mockResolvedValue({ checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
success: false, success: false,
error: 'Unauthorized', error: 'Unauthorized',
}), }),
@@ -304,7 +304,7 @@ describe('Custom Tools API Routes', () => {
describe('POST /api/tools/custom', () => { describe('POST /api/tools/custom', () => {
it('should reject unauthorized requests', async () => { it('should reject unauthorized requests', async () => {
vi.doMock('@/lib/auth/hybrid', () => ({ vi.doMock('@/lib/auth/hybrid', () => ({
checkHybridAuth: vi.fn().mockResolvedValue({ checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
success: false, success: false,
error: 'Unauthorized', error: 'Unauthorized',
}), }),
@@ -390,7 +390,7 @@ describe('Custom Tools API Routes', () => {
it('should prevent unauthorized deletion of user-scoped tool', async () => { it('should prevent unauthorized deletion of user-scoped tool', async () => {
vi.doMock('@/lib/auth/hybrid', () => ({ vi.doMock('@/lib/auth/hybrid', () => ({
checkHybridAuth: vi.fn().mockResolvedValue({ checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
success: true, success: true,
userId: 'user-456', userId: 'user-456',
authType: 'session', authType: 'session',
@@ -413,7 +413,7 @@ describe('Custom Tools API Routes', () => {
it('should reject unauthorized requests', async () => { it('should reject unauthorized requests', async () => {
vi.doMock('@/lib/auth/hybrid', () => ({ vi.doMock('@/lib/auth/hybrid', () => ({
checkHybridAuth: vi.fn().mockResolvedValue({ checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
success: false, success: false,
error: 'Unauthorized', error: 'Unauthorized',
}), }),

View File

@@ -4,7 +4,7 @@ import { createLogger } from '@sim/logger'
import { and, desc, eq, isNull, or } from 'drizzle-orm' import { and, desc, eq, isNull, or } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { upsertCustomTools } from '@/lib/workflows/custom-tools/operations' import { upsertCustomTools } from '@/lib/workflows/custom-tools/operations'
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils' import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
@@ -42,8 +42,8 @@ export async function GET(request: NextRequest) {
const workflowId = searchParams.get('workflowId') const workflowId = searchParams.get('workflowId')
try { try {
// Use hybrid auth to support session, API key, and internal JWT // Use session/internal auth to support session and internal JWT (no API key access)
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkSessionOrInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success || !authResult.userId) { if (!authResult.success || !authResult.userId) {
logger.warn(`[${requestId}] Unauthorized custom tools access attempt`) logger.warn(`[${requestId}] Unauthorized custom tools access attempt`)
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
@@ -69,8 +69,8 @@ export async function GET(request: NextRequest) {
} }
// Check workspace permissions // Check workspace permissions
// For internal JWT with workflowId: checkHybridAuth already resolved userId from workflow owner // For internal JWT with workflowId: checkSessionOrInternalAuth already resolved userId from workflow owner
// For session/API key: verify user has access to the workspace // For session: verify user has access to the workspace
// For legacy (no workspaceId): skip workspace check, rely on userId match // For legacy (no workspaceId): skip workspace check, rely on userId match
if (resolvedWorkspaceId && !(authResult.authType === 'internal_jwt' && workflowId)) { if (resolvedWorkspaceId && !(authResult.authType === 'internal_jwt' && workflowId)) {
const userPermission = await getUserEntityPermissions( const userPermission = await getUserEntityPermissions(
@@ -116,8 +116,8 @@ export async function POST(req: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
// Use hybrid auth (though this endpoint is only called from UI) // Use session/internal auth (no API key access)
const authResult = await checkHybridAuth(req, { requireWorkflowId: false }) const authResult = await checkSessionOrInternalAuth(req, { requireWorkflowId: false })
if (!authResult.success || !authResult.userId) { if (!authResult.success || !authResult.userId) {
logger.warn(`[${requestId}] Unauthorized custom tools update attempt`) logger.warn(`[${requestId}] Unauthorized custom tools update attempt`)
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
@@ -193,8 +193,8 @@ export async function DELETE(request: NextRequest) {
} }
try { try {
// Use hybrid auth (though this endpoint is only called from UI) // Use session/internal auth (no API key access)
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkSessionOrInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success || !authResult.userId) { if (!authResult.success || !authResult.userId) {
logger.warn(`[${requestId}] Unauthorized custom tool deletion attempt`) logger.warn(`[${requestId}] Unauthorized custom tool deletion attempt`)
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { validateNumericId } from '@/lib/core/security/input-validation' import { validateNumericId } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Discord send attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Discord send attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { validateAlphanumericId } from '@/lib/core/security/input-validation' import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail add label attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail add label attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail archive attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail archive attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail delete attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail delete attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail draft attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail draft attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail mark read attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail mark read attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail mark unread attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail mark unread attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail move attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail move attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { validateAlphanumericId } from '@/lib/core/security/input-validation' import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail remove label attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail remove label attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail send attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail send attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Gmail unarchive attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Gmail unarchive attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils' import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -56,7 +56,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Google Drive upload attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Google Drive upload attempt: ${authResult.error}`)

View File

@@ -1,6 +1,6 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { validateImageUrl } from '@/lib/core/security/input-validation' import { validateImageUrl } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
@@ -15,7 +15,7 @@ export async function GET(request: NextRequest) {
const imageUrl = url.searchParams.get('url') const imageUrl = url.searchParams.get('url')
const requestId = generateRequestId() const requestId = generateRequestId()
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.error(`[${requestId}] Authentication failed for image proxy:`, authResult.error) logger.error(`[${requestId}] Authentication failed for image proxy:`, authResult.error)
return new NextResponse('Unauthorized', { status: 401 }) return new NextResponse('Unauthorized', { status: 401 })

View File

@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { Resend } from 'resend' import { Resend } from 'resend'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized mail send attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized mail send attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Teams chat delete attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Teams chat delete attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Teams channel write attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Teams channel write attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Teams chat write attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Teams chat write attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { getBaseUrl } from '@/lib/core/utils/urls' import { getBaseUrl } from '@/lib/core/utils/urls'
import { StorageService } from '@/lib/uploads' import { StorageService } from '@/lib/uploads'
@@ -30,7 +30,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success || !authResult.userId) { if (!authResult.success || !authResult.userId) {
logger.warn(`[${requestId}] Unauthorized Mistral parse attempt`, { logger.warn(`[${requestId}] Unauthorized Mistral parse attempt`, {

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { buildDeleteQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils' import { buildDeleteQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
const logger = createLogger('MySQLDeleteAPI') const logger = createLogger('MySQLDeleteAPI')
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized MySQL delete attempt`) logger.warn(`[${requestId}] Unauthorized MySQL delete attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils' import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils'
const logger = createLogger('MySQLExecuteAPI') const logger = createLogger('MySQLExecuteAPI')
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized MySQL execute attempt`) logger.warn(`[${requestId}] Unauthorized MySQL execute attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { buildInsertQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils' import { buildInsertQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
const logger = createLogger('MySQLInsertAPI') const logger = createLogger('MySQLInsertAPI')
@@ -43,7 +43,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized MySQL insert attempt`) logger.warn(`[${requestId}] Unauthorized MySQL insert attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createMySQLConnection, executeIntrospect } from '@/app/api/tools/mysql/utils' import { createMySQLConnection, executeIntrospect } from '@/app/api/tools/mysql/utils'
const logger = createLogger('MySQLIntrospectAPI') const logger = createLogger('MySQLIntrospectAPI')
@@ -20,7 +20,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized MySQL introspect attempt`) logger.warn(`[${requestId}] Unauthorized MySQL introspect attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils' import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils'
const logger = createLogger('MySQLQueryAPI') const logger = createLogger('MySQLQueryAPI')
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized MySQL query attempt`) logger.warn(`[${requestId}] Unauthorized MySQL query attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { buildUpdateQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils' import { buildUpdateQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
const logger = createLogger('MySQLUpdateAPI') const logger = createLogger('MySQLUpdateAPI')
@@ -41,7 +41,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized MySQL update attempt`) logger.warn(`[${requestId}] Unauthorized MySQL update attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import * as XLSX from 'xlsx' import * as XLSX from 'xlsx'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation' import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { import {
@@ -39,7 +39,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized OneDrive upload attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized OneDrive upload attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Outlook copy attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Outlook copy attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Outlook delete attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Outlook delete attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Outlook draft attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Outlook draft attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Outlook mark read attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Outlook mark read attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Outlook mark unread attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Outlook mark unread attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Outlook move attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Outlook move attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Outlook send attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Outlook send attempt: ${authResult.error}`)

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createPostgresConnection, executeDelete } from '@/app/api/tools/postgresql/utils' import { createPostgresConnection, executeDelete } from '@/app/api/tools/postgresql/utils'
const logger = createLogger('PostgreSQLDeleteAPI') const logger = createLogger('PostgreSQLDeleteAPI')
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized PostgreSQL delete attempt`) logger.warn(`[${requestId}] Unauthorized PostgreSQL delete attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { import {
createPostgresConnection, createPostgresConnection,
executeQuery, executeQuery,
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized PostgreSQL execute attempt`) logger.warn(`[${requestId}] Unauthorized PostgreSQL execute attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createPostgresConnection, executeInsert } from '@/app/api/tools/postgresql/utils' import { createPostgresConnection, executeInsert } from '@/app/api/tools/postgresql/utils'
const logger = createLogger('PostgreSQLInsertAPI') const logger = createLogger('PostgreSQLInsertAPI')
@@ -43,7 +43,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized PostgreSQL insert attempt`) logger.warn(`[${requestId}] Unauthorized PostgreSQL insert attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createPostgresConnection, executeIntrospect } from '@/app/api/tools/postgresql/utils' import { createPostgresConnection, executeIntrospect } from '@/app/api/tools/postgresql/utils'
const logger = createLogger('PostgreSQLIntrospectAPI') const logger = createLogger('PostgreSQLIntrospectAPI')
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized PostgreSQL introspect attempt`) logger.warn(`[${requestId}] Unauthorized PostgreSQL introspect attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createPostgresConnection, executeQuery } from '@/app/api/tools/postgresql/utils' import { createPostgresConnection, executeQuery } from '@/app/api/tools/postgresql/utils'
const logger = createLogger('PostgreSQLQueryAPI') const logger = createLogger('PostgreSQLQueryAPI')
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized PostgreSQL query attempt`) logger.warn(`[${requestId}] Unauthorized PostgreSQL query attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createPostgresConnection, executeUpdate } from '@/app/api/tools/postgresql/utils' import { createPostgresConnection, executeUpdate } from '@/app/api/tools/postgresql/utils'
const logger = createLogger('PostgreSQLUpdateAPI') const logger = createLogger('PostgreSQLUpdateAPI')
@@ -41,7 +41,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized PostgreSQL update attempt`) logger.warn(`[${requestId}] Unauthorized PostgreSQL update attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { getBaseUrl } from '@/lib/core/utils/urls' import { getBaseUrl } from '@/lib/core/utils/urls'
import { StorageService } from '@/lib/uploads' import { StorageService } from '@/lib/uploads'
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success || !authResult.userId) { if (!authResult.success || !authResult.userId) {
logger.warn(`[${requestId}] Unauthorized Pulse parse attempt`, { logger.warn(`[${requestId}] Unauthorized Pulse parse attempt`, {

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { getBaseUrl } from '@/lib/core/utils/urls' import { getBaseUrl } from '@/lib/core/utils/urls'
import { StorageService } from '@/lib/uploads' import { StorageService } from '@/lib/uploads'
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success || !authResult.userId) { if (!authResult.success || !authResult.userId) {
logger.warn(`[${requestId}] Unauthorized Reducto parse attempt`, { logger.warn(`[${requestId}] Unauthorized Reducto parse attempt`, {

View File

@@ -2,7 +2,7 @@ import { CopyObjectCommand, type ObjectCannedACL, S3Client } from '@aws-sdk/clie
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -24,7 +24,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized S3 copy object attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized S3 copy object attempt: ${authResult.error}`)

View File

@@ -2,7 +2,7 @@ import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized S3 delete object attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized S3 delete object attempt: ${authResult.error}`)

View File

@@ -2,7 +2,7 @@ import { ListObjectsV2Command, S3Client } from '@aws-sdk/client-s3'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized S3 list objects attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized S3 list objects attempt: ${authResult.error}`)

View File

@@ -2,7 +2,7 @@ import { type ObjectCannedACL, PutObjectCommand, S3Client } from '@aws-sdk/clien
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils' import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized S3 put object attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized S3 put object attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { SEARCH_TOOL_COST } from '@/lib/billing/constants' import { SEARCH_TOOL_COST } from '@/lib/billing/constants'
import { env } from '@/lib/core/config/env' import { env } from '@/lib/core/config/env'
import { executeTool } from '@/tools' import { executeTool } from '@/tools'
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const { searchParams: urlParams } = new URL(request.url) const { searchParams: urlParams } = new URL(request.url)
const workflowId = urlParams.get('workflowId') || undefined const workflowId = urlParams.get('workflowId') || undefined
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success || !authResult.userId) { if (!authResult.success || !authResult.userId) {
const errorMessage = workflowId ? 'Workflow not found' : authResult.error || 'Unauthorized' const errorMessage = workflowId ? 'Workflow not found' : authResult.error || 'Unauthorized'

View File

@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import type { SFTPWrapper } from 'ssh2' import type { SFTPWrapper } from 'ssh2'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { import {
createSftpConnection, createSftpConnection,
@@ -72,7 +72,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized SFTP delete attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized SFTP delete attempt: ${authResult.error}`)

View File

@@ -2,7 +2,7 @@ import path from 'path'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { createSftpConnection, getSftp, isPathSafe, sanitizePath } from '@/app/api/tools/sftp/utils' import { createSftpConnection, getSftp, isPathSafe, sanitizePath } from '@/app/api/tools/sftp/utils'
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized SFTP download attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized SFTP download attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { import {
createSftpConnection, createSftpConnection,
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized SFTP list attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized SFTP list attempt: ${authResult.error}`)

View File

@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import type { SFTPWrapper } from 'ssh2' import type { SFTPWrapper } from 'ssh2'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { import {
createSftpConnection, createSftpConnection,
@@ -60,7 +60,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized SFTP mkdir attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized SFTP mkdir attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -44,7 +44,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized SFTP upload attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized SFTP upload attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized SharePoint upload attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized SharePoint upload attempt: ${authResult.error}`)

View File

@@ -1,6 +1,6 @@
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -13,7 +13,7 @@ const SlackAddReactionSchema = z.object({
export async function POST(request: NextRequest) { export async function POST(request: NextRequest) {
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
return NextResponse.json( return NextResponse.json(

View File

@@ -1,6 +1,6 @@
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -12,7 +12,7 @@ const SlackDeleteMessageSchema = z.object({
export async function POST(request: NextRequest) { export async function POST(request: NextRequest) {
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
return NextResponse.json( return NextResponse.json(

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { openDMChannel } from '../utils' import { openDMChannel } from '../utils'
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Slack read messages attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Slack read messages attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { sendSlackMessage } from '../utils' import { sendSlackMessage } from '../utils'
@@ -26,7 +26,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Slack send attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Slack send attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
export const dynamic = 'force-dynamic' export const dynamic = 'force-dynamic'
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Slack update message attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Slack update message attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { env } from '@/lib/core/config/env' import { env } from '@/lib/core/config/env'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { type SMSOptions, sendSMS } from '@/lib/messaging/sms/service' import { type SMSOptions, sendSMS } from '@/lib/messaging/sms/service'
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized SMS send attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized SMS send attempt: ${authResult.error}`)

View File

@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import nodemailer from 'nodemailer' import nodemailer from 'nodemailer'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized SMTP send attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized SMTP send attempt: ${authResult.error}`)

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils' import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils'
const logger = createLogger('SSHCheckCommandExistsAPI') const logger = createLogger('SSHCheckCommandExistsAPI')
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH check command exists attempt`) logger.warn(`[${requestId}] Unauthorized SSH check command exists attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import type { Client, SFTPWrapper, Stats } from 'ssh2' import type { Client, SFTPWrapper, Stats } from 'ssh2'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { import {
createSSHConnection, createSSHConnection,
getFileType, getFileType,
@@ -40,7 +40,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH check file exists attempt`) logger.warn(`[${requestId}] Unauthorized SSH check file exists attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { import {
createSSHConnection, createSSHConnection,
escapeShellArg, escapeShellArg,
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH create directory attempt`) logger.warn(`[${requestId}] Unauthorized SSH create directory attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { import {
createSSHConnection, createSSHConnection,
escapeShellArg, escapeShellArg,
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH delete file attempt`) logger.warn(`[${requestId}] Unauthorized SSH delete file attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -4,7 +4,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import type { Client, SFTPWrapper } from 'ssh2' import type { Client, SFTPWrapper } from 'ssh2'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils' import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
const logger = createLogger('SSHDownloadFileAPI') const logger = createLogger('SSHDownloadFileAPI')
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH download file attempt`) logger.warn(`[${requestId}] Unauthorized SSH download file attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createSSHConnection, executeSSHCommand, sanitizeCommand } from '@/app/api/tools/ssh/utils' import { createSSHConnection, executeSSHCommand, sanitizeCommand } from '@/app/api/tools/ssh/utils'
const logger = createLogger('SSHExecuteCommandAPI') const logger = createLogger('SSHExecuteCommandAPI')
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH execute command attempt`) logger.warn(`[${requestId}] Unauthorized SSH execute command attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils' import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils'
const logger = createLogger('SSHExecuteScriptAPI') const logger = createLogger('SSHExecuteScriptAPI')
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH execute script attempt`) logger.warn(`[${requestId}] Unauthorized SSH execute script attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createSSHConnection, executeSSHCommand } from '@/app/api/tools/ssh/utils' import { createSSHConnection, executeSSHCommand } from '@/app/api/tools/ssh/utils'
const logger = createLogger('SSHGetSystemInfoAPI') const logger = createLogger('SSHGetSystemInfoAPI')
@@ -20,7 +20,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH get system info attempt`) logger.warn(`[${requestId}] Unauthorized SSH get system info attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import type { Client, FileEntry, SFTPWrapper } from 'ssh2' import type { Client, FileEntry, SFTPWrapper } from 'ssh2'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { import {
createSSHConnection, createSSHConnection,
getFileType, getFileType,
@@ -61,7 +61,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH list directory attempt`) logger.warn(`[${requestId}] Unauthorized SSH list directory attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { import {
createSSHConnection, createSSHConnection,
escapeShellArg, escapeShellArg,
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH move/rename attempt`) logger.warn(`[${requestId}] Unauthorized SSH move/rename attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import type { Client, SFTPWrapper } from 'ssh2' import type { Client, SFTPWrapper } from 'ssh2'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils' import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
const logger = createLogger('SSHReadFileContentAPI') const logger = createLogger('SSHReadFileContentAPI')
@@ -36,7 +36,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH read file content attempt`) logger.warn(`[${requestId}] Unauthorized SSH read file content attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import type { Client, SFTPWrapper } from 'ssh2' import type { Client, SFTPWrapper } from 'ssh2'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils' import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
const logger = createLogger('SSHUploadFileAPI') const logger = createLogger('SSHUploadFileAPI')
@@ -38,7 +38,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH upload file attempt`) logger.warn(`[${requestId}] Unauthorized SSH upload file attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import type { Client, SFTPWrapper } from 'ssh2' import type { Client, SFTPWrapper } from 'ssh2'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils' import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
const logger = createLogger('SSHWriteFileContentAPI') const logger = createLogger('SSHWriteFileContentAPI')
@@ -37,7 +37,7 @@ export async function POST(request: NextRequest) {
const requestId = randomUUID().slice(0, 8) const requestId = randomUUID().slice(0, 8)
try { try {
const auth = await checkHybridAuth(request) const auth = await checkInternalAuth(request)
if (!auth.success || !auth.userId) { if (!auth.success || !auth.userId) {
logger.warn(`[${requestId}] Unauthorized SSH write file content attempt`) logger.warn(`[${requestId}] Unauthorized SSH write file content attempt`)
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { extractAudioFromVideo, isVideoFile } from '@/lib/audio/extractor' import { extractAudioFromVideo, isVideoFile } from '@/lib/audio/extractor'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
import type { UserFile } from '@/executor/types' import type { UserFile } from '@/executor/types'
import type { TranscriptSegment } from '@/tools/stt/types' import type { TranscriptSegment } from '@/tools/stt/types'
@@ -40,7 +40,7 @@ export async function POST(request: NextRequest) {
logger.info(`[${requestId}] STT transcription request started`) logger.info(`[${requestId}] STT transcription request started`)
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
} }

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils' import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { const authResult = await checkInternalAuth(request, {
requireWorkflowId: false, requireWorkflowId: false,
}) })

View File

@@ -2,7 +2,7 @@ import crypto from 'crypto'
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { import {
validateAwsRegion, validateAwsRegion,
validateExternalUrl, validateExternalUrl,
@@ -292,7 +292,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success || !authResult.userId) { if (!authResult.success || !authResult.userId) {
logger.warn(`[${requestId}] Unauthorized Textract parse attempt`, { logger.warn(`[${requestId}] Unauthorized Textract parse attempt`, {

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import type { NextRequest } from 'next/server' import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server' import { NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { validateAlphanumericId } from '@/lib/core/security/input-validation' import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import { getBaseUrl } from '@/lib/core/utils/urls' import { getBaseUrl } from '@/lib/core/utils/urls'
import { StorageService } from '@/lib/uploads' import { StorageService } from '@/lib/uploads'
@@ -10,7 +10,7 @@ const logger = createLogger('ProxyTTSAPI')
export async function POST(request: NextRequest) { export async function POST(request: NextRequest) {
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.error('Authentication failed for TTS proxy:', authResult.error) logger.error('Authentication failed for TTS proxy:', authResult.error)
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import type { NextRequest } from 'next/server' import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server' import { NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { validateAlphanumericId } from '@/lib/core/security/input-validation' import { validateAlphanumericId } from '@/lib/core/security/input-validation'
import { getBaseUrl } from '@/lib/core/utils/urls' import { getBaseUrl } from '@/lib/core/utils/urls'
import { StorageService } from '@/lib/uploads' import { StorageService } from '@/lib/uploads'
@@ -87,7 +87,7 @@ export async function POST(request: NextRequest) {
logger.info(`[${requestId}] TTS unified request started`) logger.info(`[${requestId}] TTS unified request started`)
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.error('Authentication failed for TTS unified proxy:', authResult.error) logger.error('Authentication failed for TTS unified proxy:', authResult.error)
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })

View File

@@ -1,6 +1,6 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
import type { UserFile } from '@/executor/types' import type { UserFile } from '@/executor/types'
import type { VideoRequestBody } from '@/tools/video/types' import type { VideoRequestBody } from '@/tools/video/types'
@@ -15,7 +15,7 @@ export async function POST(request: NextRequest) {
logger.info(`[${requestId}] Video generation request started`) logger.info(`[${requestId}] Video generation request started`)
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
} }

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils' import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server' import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized Vision analyze attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized Vision analyze attempt: ${authResult.error}`)

View File

@@ -1,7 +1,7 @@
import { createLogger } from '@sim/logger' import { createLogger } from '@sim/logger'
import { type NextRequest, NextResponse } from 'next/server' import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod' import { z } from 'zod'
import { checkHybridAuth } from '@/lib/auth/hybrid' import { checkInternalAuth } from '@/lib/auth/hybrid'
import { generateRequestId } from '@/lib/core/utils/request' import { generateRequestId } from '@/lib/core/utils/request'
import { import {
getFileExtension, getFileExtension,
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
const requestId = generateRequestId() const requestId = generateRequestId()
try { try {
const authResult = await checkHybridAuth(request, { requireWorkflowId: false }) const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
if (!authResult.success) { if (!authResult.success) {
logger.warn(`[${requestId}] Unauthorized WordPress upload attempt: ${authResult.error}`) logger.warn(`[${requestId}] Unauthorized WordPress upload attempt: ${authResult.error}`)

View File

@@ -144,25 +144,22 @@ describe('AgentBlockHandler', () => {
} }
mockGetProviderFromModel.mockReturnValue('mock-provider') mockGetProviderFromModel.mockReturnValue('mock-provider')
mockFetch.mockImplementation(() => { mockExecuteProviderRequest.mockResolvedValue({
content: 'Mocked response content',
model: 'mock-model',
tokens: { input: 10, output: 20, total: 30 },
toolCalls: [],
cost: 0.001,
timing: { total: 100 },
})
mockFetch.mockImplementation((url: string) => {
return Promise.resolve({ return Promise.resolve({
ok: true, ok: true,
headers: { headers: {
get: (name: string) => { get: () => null,
if (name === 'Content-Type') return 'application/json'
if (name === 'X-Execution-Data') return null
return null
},
}, },
json: () => json: () => Promise.resolve({}),
Promise.resolve({
content: 'Mocked response content',
model: 'mock-model',
tokens: { input: 10, output: 20, total: 30 },
toolCalls: [],
cost: 0.001,
timing: { total: 100 },
}),
}) })
}) })
@@ -244,7 +241,7 @@ describe('AgentBlockHandler', () => {
const result = await handler.execute(mockContext, mockBlock, inputs) const result = await handler.execute(mockContext, mockBlock, inputs)
expect(mockGetProviderFromModel).toHaveBeenCalledWith('gpt-4o') expect(mockGetProviderFromModel).toHaveBeenCalledWith('gpt-4o')
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object)) expect(mockExecuteProviderRequest).toHaveBeenCalled()
expect(result).toEqual(expectedOutput) expect(result).toEqual(expectedOutput)
}) })
@@ -263,34 +260,21 @@ describe('AgentBlockHandler', () => {
return result return result
}) })
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: 'Using tools to respond',
ok: true, model: 'mock-model',
headers: { tokens: { input: 10, output: 20, total: 30 },
get: (name: string) => { toolCalls: [
if (name === 'Content-Type') return 'application/json' {
if (name === 'X-Execution-Data') return null name: 'auto_tool',
return null arguments: { input: 'test input for auto tool' },
},
}, },
json: () => {
Promise.resolve({ name: 'force_tool',
content: 'Using tools to respond', arguments: { input: 'test input for force tool' },
model: 'mock-model', },
tokens: { input: 10, output: 20, total: 30 }, ],
toolCalls: [ timing: { total: 100 },
{
name: 'auto_tool',
arguments: { input: 'test input for auto tool' },
},
{
name: 'force_tool',
arguments: { input: 'test input for force tool' },
},
],
timing: { total: 100 },
}),
})
}) })
const inputs = { const inputs = {
@@ -403,8 +387,8 @@ describe('AgentBlockHandler', () => {
expect.any(Object) // execution context expect.any(Object) // execution context
) )
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
expect(requestBody.tools.length).toBe(2) expect(requestBody.tools.length).toBe(2)
}) })
@@ -443,8 +427,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
expect(requestBody.tools.length).toBe(2) expect(requestBody.tools.length).toBe(2)
@@ -488,8 +472,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
expect(requestBody.tools[0].usageControl).toBe('auto') expect(requestBody.tools[0].usageControl).toBe('auto')
expect(requestBody.tools[1].usageControl).toBe('force') expect(requestBody.tools[1].usageControl).toBe('force')
@@ -553,8 +537,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
expect(requestBody.tools.length).toBe(2) expect(requestBody.tools.length).toBe(2)
@@ -583,7 +567,7 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object)) expect(mockExecuteProviderRequest).toHaveBeenCalled()
}) })
it('should execute with standard block tools', async () => { it('should execute with standard block tools', async () => {
@@ -625,7 +609,7 @@ describe('AgentBlockHandler', () => {
inputs.tools[0], inputs.tools[0],
expect.objectContaining({ selectedOperation: 'analyze' }) expect.objectContaining({ selectedOperation: 'analyze' })
) )
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object)) expect(mockExecuteProviderRequest).toHaveBeenCalled()
expect(result).toEqual(expectedOutput) expect(result).toEqual(expectedOutput)
}) })
@@ -676,30 +660,17 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object)) expect(mockExecuteProviderRequest).toHaveBeenCalled()
}) })
it('should handle responseFormat with valid JSON', async () => { it('should handle responseFormat with valid JSON', async () => {
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: '{"result": "Success", "score": 0.95}',
ok: true, model: 'mock-model',
headers: { tokens: { input: 10, output: 20, total: 30 },
get: (name: string) => { timing: { total: 100 },
if (name === 'Content-Type') return 'application/json' toolCalls: [],
if (name === 'X-Execution-Data') return null cost: undefined,
return null
},
},
json: () =>
Promise.resolve({
content: '{"result": "Success", "score": 0.95}',
model: 'mock-model',
tokens: { input: 10, output: 20, total: 30 },
timing: { total: 100 },
toolCalls: [],
cost: undefined,
}),
})
}) })
const inputs = { const inputs = {
@@ -723,24 +694,11 @@ describe('AgentBlockHandler', () => {
}) })
it('should handle responseFormat when it is an empty string', async () => { it('should handle responseFormat when it is an empty string', async () => {
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: 'Regular text response',
ok: true, model: 'mock-model',
headers: { tokens: { input: 10, output: 20, total: 30 },
get: (name: string) => { timing: { total: 100 },
if (name === 'Content-Type') return 'application/json'
if (name === 'X-Execution-Data') return null
return null
},
},
json: () =>
Promise.resolve({
content: 'Regular text response',
model: 'mock-model',
tokens: { input: 10, output: 20, total: 30 },
timing: { total: 100 },
}),
})
}) })
const inputs = { const inputs = {
@@ -763,26 +721,13 @@ describe('AgentBlockHandler', () => {
}) })
it('should handle invalid JSON in responseFormat gracefully', async () => { it('should handle invalid JSON in responseFormat gracefully', async () => {
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: 'Regular text response',
ok: true, model: 'mock-model',
headers: { tokens: { input: 10, output: 20, total: 30 },
get: (name: string) => { timing: { total: 100 },
if (name === 'Content-Type') return 'application/json' toolCalls: [],
if (name === 'X-Execution-Data') return null cost: undefined,
return null
},
},
json: () =>
Promise.resolve({
content: 'Regular text response',
model: 'mock-model',
tokens: { input: 10, output: 20, total: 30 },
timing: { total: 100 },
toolCalls: [],
cost: undefined,
}),
})
}) })
const inputs = { const inputs = {
@@ -806,26 +751,13 @@ describe('AgentBlockHandler', () => {
}) })
it('should handle variable references in responseFormat gracefully', async () => { it('should handle variable references in responseFormat gracefully', async () => {
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: 'Regular text response',
ok: true, model: 'mock-model',
headers: { tokens: { input: 10, output: 20, total: 30 },
get: (name: string) => { timing: { total: 100 },
if (name === 'Content-Type') return 'application/json' toolCalls: [],
if (name === 'X-Execution-Data') return null cost: undefined,
return null
},
},
json: () =>
Promise.resolve({
content: 'Regular text response',
model: 'mock-model',
tokens: { input: 10, output: 20, total: 30 },
timing: { total: 100 },
toolCalls: [],
cost: undefined,
}),
})
}) })
const inputs = { const inputs = {
@@ -856,7 +788,7 @@ describe('AgentBlockHandler', () => {
} }
mockGetProviderFromModel.mockReturnValue('openai') mockGetProviderFromModel.mockReturnValue('openai')
mockFetch.mockRejectedValue(new Error('Provider API Error')) mockExecuteProviderRequest.mockRejectedValueOnce(new Error('Provider API Error'))
await expect(handler.execute(mockContext, mockBlock, inputs)).rejects.toThrow( await expect(handler.execute(mockContext, mockBlock, inputs)).rejects.toThrow(
'Provider API Error' 'Provider API Error'
@@ -870,30 +802,17 @@ describe('AgentBlockHandler', () => {
}, },
}) })
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ stream: mockStreamBody,
ok: true, execution: {
headers: { success: true,
get: (name: string) => { output: {},
if (name === 'Content-Type') return 'application/json' logs: [],
if (name === 'X-Execution-Data') return null metadata: {
return null duration: 0,
}, startTime: new Date().toISOString(),
}, },
json: () => },
Promise.resolve({
stream: mockStreamBody,
execution: {
success: true,
output: {},
logs: [],
metadata: {
duration: 0,
startTime: new Date().toISOString(),
},
},
}),
})
}) })
const inputs = { const inputs = {
@@ -947,22 +866,9 @@ describe('AgentBlockHandler', () => {
}, },
} }
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ stream: mockStreamBody,
ok: true, execution: mockExecutionData,
headers: {
get: (name: string) => {
if (name === 'Content-Type') return 'application/json'
if (name === 'X-Execution-Data') return JSON.stringify(mockExecutionData)
return null
},
},
json: () =>
Promise.resolve({
stream: mockStreamBody,
execution: mockExecutionData,
}),
})
}) })
const inputs = { const inputs = {
@@ -996,30 +902,21 @@ describe('AgentBlockHandler', () => {
}, },
}) })
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ stream: {}, // Serialized stream placeholder
ok: true, execution: {
headers: { success: true,
get: (name: string) => (name === 'Content-Type' ? 'application/json' : null), output: {
content: 'Test streaming content',
model: 'gpt-4o',
tokens: { input: 10, output: 5, total: 15 },
}, },
json: () => logs: [],
Promise.resolve({ metadata: {
stream: {}, // Serialized stream placeholder startTime: new Date().toISOString(),
execution: { duration: 150,
success: true, },
output: { },
content: 'Test streaming content',
model: 'gpt-4o',
tokens: { input: 10, output: 5, total: 15 },
},
logs: [],
metadata: {
startTime: new Date().toISOString(),
duration: 150,
},
},
}),
})
}) })
const inputs = { const inputs = {
@@ -1060,8 +957,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Verify messages were built correctly // Verify messages were built correctly
expect(requestBody.messages).toBeDefined() expect(requestBody.messages).toBeDefined()
@@ -1110,8 +1007,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Verify messages were built correctly // Verify messages were built correctly
expect(requestBody.messages).toBeDefined() expect(requestBody.messages).toBeDefined()
@@ -1149,8 +1046,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Verify messages were built correctly // Verify messages were built correctly
expect(requestBody.messages).toBeDefined() expect(requestBody.messages).toBeDefined()
@@ -1181,8 +1078,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Verify messages were built correctly // Verify messages were built correctly
// Agent system (1) + legacy memories (3) + user from messages (1) = 5 // Agent system (1) + legacy memories (3) + user from messages (1) = 5
@@ -1225,8 +1122,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Verify messages were built correctly // Verify messages were built correctly
expect(requestBody.messages).toBeDefined() expect(requestBody.messages).toBeDefined()
@@ -1268,8 +1165,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Verify messages were built correctly // Verify messages were built correctly
expect(requestBody.messages).toBeDefined() expect(requestBody.messages).toBeDefined()
@@ -1310,8 +1207,8 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Verify user prompt content was extracted correctly // Verify user prompt content was extracted correctly
expect(requestBody.messages).toBeDefined() expect(requestBody.messages).toBeDefined()
@@ -1337,15 +1234,14 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object)) expect(mockExecuteProviderRequest).toHaveBeenCalled()
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Check that Azure parameters are included in the request
expect(requestBody.azureEndpoint).toBe('https://my-azure-resource.openai.azure.com') expect(requestBody.azureEndpoint).toBe('https://my-azure-resource.openai.azure.com')
expect(requestBody.azureApiVersion).toBe('2024-07-01-preview') expect(requestBody.azureApiVersion).toBe('2024-07-01-preview')
expect(requestBody.provider).toBe('azure-openai') expect(providerCall[0]).toBe('azure-openai')
expect(requestBody.model).toBe('azure/gpt-4o') expect(requestBody.model).toBe('azure/gpt-4o')
expect(requestBody.apiKey).toBe('test-azure-api-key') expect(requestBody.apiKey).toBe('test-azure-api-key')
}) })
@@ -1365,15 +1261,14 @@ describe('AgentBlockHandler', () => {
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object)) expect(mockExecuteProviderRequest).toHaveBeenCalled()
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Check that GPT-5 parameters are included in the request
expect(requestBody.reasoningEffort).toBe('minimal') expect(requestBody.reasoningEffort).toBe('minimal')
expect(requestBody.verbosity).toBe('high') expect(requestBody.verbosity).toBe('high')
expect(requestBody.provider).toBe('openai') expect(providerCall[0]).toBe('openai')
expect(requestBody.model).toBe('gpt-5') expect(requestBody.model).toBe('gpt-5')
expect(requestBody.apiKey).toBe('test-api-key') expect(requestBody.apiKey).toBe('test-api-key')
}) })
@@ -1385,22 +1280,20 @@ describe('AgentBlockHandler', () => {
userPrompt: 'Hello!', userPrompt: 'Hello!',
apiKey: 'test-api-key', apiKey: 'test-api-key',
temperature: 0.7, temperature: 0.7,
// No reasoningEffort or verbosity provided
} }
mockGetProviderFromModel.mockReturnValue('openai') mockGetProviderFromModel.mockReturnValue('openai')
await handler.execute(mockContext, mockBlock, inputs) await handler.execute(mockContext, mockBlock, inputs)
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object)) expect(mockExecuteProviderRequest).toHaveBeenCalled()
const fetchCall = mockFetch.mock.calls[0] const providerCall = mockExecuteProviderRequest.mock.calls[0]
const requestBody = JSON.parse(fetchCall[1].body) const requestBody = providerCall[1]
// Check that GPT-5 parameters are undefined when not provided
expect(requestBody.reasoningEffort).toBeUndefined() expect(requestBody.reasoningEffort).toBeUndefined()
expect(requestBody.verbosity).toBeUndefined() expect(requestBody.verbosity).toBeUndefined()
expect(requestBody.provider).toBe('openai') expect(providerCall[0]).toBe('openai')
expect(requestBody.model).toBe('gpt-5') expect(requestBody.model).toBe('gpt-5')
}) })
@@ -1422,42 +1315,29 @@ describe('AgentBlockHandler', () => {
return Promise.resolve({ success: false, error: 'Unknown tool' }) return Promise.resolve({ success: false, error: 'Unknown tool' })
}) })
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: 'I will use MCP tools to help you.',
ok: true, model: 'gpt-4o',
headers: { tokens: { input: 15, output: 25, total: 40 },
get: (name: string) => { toolCalls: [
if (name === 'Content-Type') return 'application/json' {
if (name === 'X-Execution-Data') return null name: 'mcp-server1-list_files',
return null arguments: { path: '/tmp' },
result: {
success: true,
output: { content: [{ type: 'text', text: 'Files listed' }] },
}, },
}, },
json: () => {
Promise.resolve({ name: 'mcp-server2-search',
content: 'I will use MCP tools to help you.', arguments: { query: 'test', limit: 5 },
model: 'gpt-4o', result: {
tokens: { input: 15, output: 25, total: 40 }, success: true,
toolCalls: [ output: { content: [{ type: 'text', text: 'Search results' }] },
{ },
name: 'mcp-server1-list_files', },
arguments: { path: '/tmp' }, ],
result: { timing: { total: 150 },
success: true,
output: { content: [{ type: 'text', text: 'Files listed' }] },
},
},
{
name: 'mcp-server2-search',
arguments: { query: 'test', limit: 5 },
result: {
success: true,
output: { content: [{ type: 'text', text: 'Search results' }] },
},
},
],
timing: { total: 150 },
}),
})
}) })
const inputs = { const inputs = {
@@ -1533,34 +1413,21 @@ describe('AgentBlockHandler', () => {
return Promise.resolve({ success: false, error: 'Unknown tool' }) return Promise.resolve({ success: false, error: 'Unknown tool' })
}) })
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: 'Let me try to use this tool.',
ok: true, model: 'gpt-4o',
headers: { tokens: { input: 10, output: 15, total: 25 },
get: (name: string) => { toolCalls: [
if (name === 'Content-Type') return 'application/json' {
if (name === 'X-Execution-Data') return null name: 'mcp-server1-failing_tool',
return null arguments: { param: 'value' },
result: {
success: false,
error: 'MCP server connection failed',
}, },
}, },
json: () => ],
Promise.resolve({ timing: { total: 100 },
content: 'Let me try to use this tool.',
model: 'gpt-4o',
tokens: { input: 10, output: 15, total: 25 },
toolCalls: [
{
name: 'mcp-server1-failing_tool',
arguments: { param: 'value' },
result: {
success: false,
error: 'MCP server connection failed',
},
},
],
timing: { total: 100 },
}),
})
}) })
const inputs = { const inputs = {
@@ -1638,25 +1505,12 @@ describe('AgentBlockHandler', () => {
mockGetProviderFromModel.mockReturnValue('openai') mockGetProviderFromModel.mockReturnValue('openai')
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: 'Used MCP tools successfully',
ok: true, model: 'gpt-4o',
headers: { tokens: { input: 20, output: 30, total: 50 },
get: (name: string) => { toolCalls: [],
if (name === 'Content-Type') return 'application/json' timing: { total: 200 },
if (name === 'X-Execution-Data') return null
return null
},
},
json: () =>
Promise.resolve({
content: 'Used MCP tools successfully',
model: 'gpt-4o',
tokens: { input: 20, output: 30, total: 50 },
toolCalls: [],
timing: { total: 200 },
}),
})
}) })
mockTransformBlockTool.mockImplementation((tool: any) => ({ mockTransformBlockTool.mockImplementation((tool: any) => ({
@@ -1669,11 +1523,9 @@ describe('AgentBlockHandler', () => {
const result = await handler.execute(mockContext, mockBlock, inputs) const result = await handler.execute(mockContext, mockBlock, inputs)
// Verify that the agent executed successfully with MCP tools
expect(result).toBeDefined() expect(result).toBeDefined()
expect(mockFetch).toHaveBeenCalled() expect(mockExecuteProviderRequest).toHaveBeenCalled()
// Verify the agent returns the expected response format
expect((result as any).content).toBe('Used MCP tools successfully') expect((result as any).content).toBe('Used MCP tools successfully')
expect((result as any).model).toBe('gpt-4o') expect((result as any).model).toBe('gpt-4o')
}) })
@@ -1691,21 +1543,12 @@ describe('AgentBlockHandler', () => {
return Promise.resolve({ success: false, error: 'Unknown tool' }) return Promise.resolve({ success: false, error: 'Unknown tool' })
}) })
mockFetch.mockImplementationOnce(() => { mockExecuteProviderRequest.mockResolvedValueOnce({
return Promise.resolve({ content: 'Using MCP tool',
ok: true, model: 'gpt-4o',
headers: { tokens: { input: 10, output: 10, total: 20 },
get: (name: string) => (name === 'Content-Type' ? 'application/json' : null), toolCalls: [{ name: 'mcp-test-tool', arguments: {} }],
}, timing: { total: 50 },
json: () =>
Promise.resolve({
content: 'Using MCP tool',
model: 'gpt-4o',
tokens: { input: 10, output: 10, total: 20 },
toolCalls: [{ name: 'mcp-test-tool', arguments: {} }],
timing: { total: 50 },
}),
})
}) })
const inputs = { const inputs = {
@@ -1815,37 +1658,26 @@ describe('AgentBlockHandler', () => {
const discoveryCalls = fetchCalls.filter((c) => c.url.includes('/api/mcp/tools/discover')) const discoveryCalls = fetchCalls.filter((c) => c.url.includes('/api/mcp/tools/discover'))
expect(discoveryCalls.length).toBe(0) expect(discoveryCalls.length).toBe(0)
const providerCalls = fetchCalls.filter((c) => c.url.includes('/api/providers')) expect(mockExecuteProviderRequest).toHaveBeenCalled()
expect(providerCalls.length).toBe(1)
}) })
it('should pass toolSchema to execution endpoint when using cached schema', async () => { it('should pass toolSchema to execution endpoint when using cached schema', async () => {
let executionCall: any = null let executionCall: any = null
mockFetch.mockImplementation((url: string, options: any) => { mockExecuteProviderRequest.mockResolvedValueOnce({
if (url.includes('/api/providers')) { content: 'Tool executed',
return Promise.resolve({ model: 'gpt-4o',
ok: true, tokens: { input: 10, output: 10, total: 20 },
headers: { toolCalls: [
get: (name: string) => (name === 'Content-Type' ? 'application/json' : null), {
}, name: 'search_files',
json: () => arguments: JSON.stringify({ query: 'test' }),
Promise.resolve({ },
content: 'Tool executed', ],
model: 'gpt-4o', timing: { total: 50 },
tokens: { input: 10, output: 10, total: 20 }, })
toolCalls: [
{
name: 'search_files',
arguments: { query: 'test' },
result: { success: true, output: {} },
},
],
timing: { total: 50 },
}),
})
}
mockFetch.mockImplementation((url: string, options: any) => {
if (url.includes('/api/mcp/tools/execute')) { if (url.includes('/api/mcp/tools/execute')) {
executionCall = { url, body: JSON.parse(options.body) } executionCall = { url, body: JSON.parse(options.body) }
return Promise.resolve({ return Promise.resolve({
@@ -1898,13 +1730,11 @@ describe('AgentBlockHandler', () => {
await handler.execute(contextWithWorkspace, mockBlock, inputs) await handler.execute(contextWithWorkspace, mockBlock, inputs)
const providerCalls = mockFetch.mock.calls.filter((c: any) => c[0].includes('/api/providers')) expect(mockExecuteProviderRequest).toHaveBeenCalled()
expect(providerCalls.length).toBe(1) const providerCallArgs = mockExecuteProviderRequest.mock.calls[0]
expect(providerCallArgs[1].tools).toBeDefined()
const providerRequestBody = JSON.parse(providerCalls[0][1].body) expect(providerCallArgs[1].tools.length).toBe(1)
expect(providerRequestBody.tools).toBeDefined() expect(providerCallArgs[1].tools[0].name).toBe('search_files')
expect(providerRequestBody.tools.length).toBe(1)
expect(providerRequestBody.tools[0].name).toBe('search_files')
}) })
it('should handle multiple MCP tools from the same server efficiently', async () => { it('should handle multiple MCP tools from the same server efficiently', async () => {
@@ -1987,14 +1817,12 @@ describe('AgentBlockHandler', () => {
const discoveryCalls = fetchCalls.filter((c) => c.url.includes('/api/mcp/tools/discover')) const discoveryCalls = fetchCalls.filter((c) => c.url.includes('/api/mcp/tools/discover'))
expect(discoveryCalls.length).toBe(0) expect(discoveryCalls.length).toBe(0)
const providerCalls = fetchCalls.filter((c) => c.url.includes('/api/providers')) expect(mockExecuteProviderRequest).toHaveBeenCalled()
expect(providerCalls.length).toBe(1) const providerCallArgs = mockExecuteProviderRequest.mock.calls[0]
expect(providerCallArgs[1].tools.length).toBe(3)
const providerRequestBody = JSON.parse(providerCalls[0].options.body)
expect(providerRequestBody.tools.length).toBe(3)
}) })
it('should should fallback to discovery for MCP tools without cached schema', async () => { it('should fallback to discovery for MCP tools without cached schema', async () => {
const fetchCalls: any[] = [] const fetchCalls: any[] = []
mockFetch.mockImplementation((url: string, options: any) => { mockFetch.mockImplementation((url: string, options: any) => {

View File

@@ -6,14 +6,7 @@ import { createMcpToolId } from '@/lib/mcp/utils'
import { refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils' import { refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils'
import { getAllBlocks } from '@/blocks' import { getAllBlocks } from '@/blocks'
import type { BlockOutput } from '@/blocks/types' import type { BlockOutput } from '@/blocks/types'
import { import { AGENT, BlockType, DEFAULTS, REFERENCE, stripCustomToolPrefix } from '@/executor/constants'
AGENT,
BlockType,
DEFAULTS,
HTTP,
REFERENCE,
stripCustomToolPrefix,
} from '@/executor/constants'
import { memoryService } from '@/executor/handlers/agent/memory' import { memoryService } from '@/executor/handlers/agent/memory'
import type { import type {
AgentInputs, AgentInputs,
@@ -23,7 +16,7 @@ import type {
} from '@/executor/handlers/agent/types' } from '@/executor/handlers/agent/types'
import type { BlockHandler, ExecutionContext, StreamingExecution } from '@/executor/types' import type { BlockHandler, ExecutionContext, StreamingExecution } from '@/executor/types'
import { collectBlockData } from '@/executor/utils/block-data' import { collectBlockData } from '@/executor/utils/block-data'
import { buildAPIUrl, buildAuthHeaders, extractAPIErrorMessage } from '@/executor/utils/http' import { buildAPIUrl, buildAuthHeaders } from '@/executor/utils/http'
import { stringifyJSON } from '@/executor/utils/json' import { stringifyJSON } from '@/executor/utils/json'
import { import {
validateBlockType, validateBlockType,
@@ -52,11 +45,9 @@ export class AgentBlockHandler implements BlockHandler {
block: SerializedBlock, block: SerializedBlock,
inputs: AgentInputs inputs: AgentInputs
): Promise<BlockOutput | StreamingExecution> { ): Promise<BlockOutput | StreamingExecution> {
// Filter out unavailable MCP tools early so they don't appear in logs/inputs
const filteredTools = await this.filterUnavailableMcpTools(ctx, inputs.tools || []) const filteredTools = await this.filterUnavailableMcpTools(ctx, inputs.tools || [])
const filteredInputs = { ...inputs, tools: filteredTools } const filteredInputs = { ...inputs, tools: filteredTools }
// Validate tool permissions before processing
await this.validateToolPermissions(ctx, filteredInputs.tools || []) await this.validateToolPermissions(ctx, filteredInputs.tools || [])
const responseFormat = this.parseResponseFormat(filteredInputs.responseFormat) const responseFormat = this.parseResponseFormat(filteredInputs.responseFormat)
@@ -80,13 +71,7 @@ export class AgentBlockHandler implements BlockHandler {
streaming: streamingConfig.shouldUseStreaming ?? false, streaming: streamingConfig.shouldUseStreaming ?? false,
}) })
const result = await this.executeProviderRequest( const result = await this.executeProviderRequest(ctx, providerRequest, block, responseFormat)
ctx,
providerRequest,
block,
responseFormat,
filteredInputs
)
if (this.isStreamingExecution(result)) { if (this.isStreamingExecution(result)) {
if (filteredInputs.memoryType && filteredInputs.memoryType !== 'none') { if (filteredInputs.memoryType && filteredInputs.memoryType !== 'none') {
@@ -996,157 +981,60 @@ export class AgentBlockHandler implements BlockHandler {
ctx: ExecutionContext, ctx: ExecutionContext,
providerRequest: any, providerRequest: any,
block: SerializedBlock, block: SerializedBlock,
responseFormat: any, responseFormat: any
inputs: AgentInputs
): Promise<BlockOutput | StreamingExecution> { ): Promise<BlockOutput | StreamingExecution> {
const providerId = providerRequest.provider const providerId = providerRequest.provider
const model = providerRequest.model const model = providerRequest.model
const providerStartTime = Date.now() const providerStartTime = Date.now()
try { try {
const isBrowser = typeof window !== 'undefined' let finalApiKey: string | undefined = providerRequest.apiKey
if (!isBrowser) { if (providerId === 'vertex' && providerRequest.vertexCredential) {
return this.executeServerSide( finalApiKey = await this.resolveVertexCredential(
ctx, providerRequest.vertexCredential,
providerRequest, ctx.workflowId
providerId,
model,
block,
responseFormat,
providerStartTime
) )
} }
return this.executeBrowserSide(
ctx, const { blockData, blockNameMapping } = collectBlockData(ctx)
providerRequest,
block, const response = await executeProviderRequest(providerId, {
responseFormat, model,
providerStartTime, systemPrompt: 'systemPrompt' in providerRequest ? providerRequest.systemPrompt : undefined,
inputs context: 'context' in providerRequest ? providerRequest.context : undefined,
) tools: providerRequest.tools,
temperature: providerRequest.temperature,
maxTokens: providerRequest.maxTokens,
apiKey: finalApiKey,
azureEndpoint: providerRequest.azureEndpoint,
azureApiVersion: providerRequest.azureApiVersion,
vertexProject: providerRequest.vertexProject,
vertexLocation: providerRequest.vertexLocation,
bedrockAccessKeyId: providerRequest.bedrockAccessKeyId,
bedrockSecretKey: providerRequest.bedrockSecretKey,
bedrockRegion: providerRequest.bedrockRegion,
responseFormat: providerRequest.responseFormat,
workflowId: providerRequest.workflowId,
workspaceId: ctx.workspaceId,
stream: providerRequest.stream,
messages: 'messages' in providerRequest ? providerRequest.messages : undefined,
environmentVariables: ctx.environmentVariables || {},
workflowVariables: ctx.workflowVariables || {},
blockData,
blockNameMapping,
isDeployedContext: ctx.isDeployedContext,
reasoningEffort: providerRequest.reasoningEffort,
verbosity: providerRequest.verbosity,
})
return this.processProviderResponse(response, block, responseFormat)
} catch (error) { } catch (error) {
this.handleExecutionError(error, providerStartTime, providerId, model, ctx, block) this.handleExecutionError(error, providerStartTime, providerId, model, ctx, block)
throw error throw error
} }
} }
private async executeServerSide(
ctx: ExecutionContext,
providerRequest: any,
providerId: string,
model: string,
block: SerializedBlock,
responseFormat: any,
providerStartTime: number
) {
let finalApiKey: string | undefined = providerRequest.apiKey
if (providerId === 'vertex' && providerRequest.vertexCredential) {
finalApiKey = await this.resolveVertexCredential(
providerRequest.vertexCredential,
ctx.workflowId
)
}
const { blockData, blockNameMapping } = collectBlockData(ctx)
const response = await executeProviderRequest(providerId, {
model,
systemPrompt: 'systemPrompt' in providerRequest ? providerRequest.systemPrompt : undefined,
context: 'context' in providerRequest ? providerRequest.context : undefined,
tools: providerRequest.tools,
temperature: providerRequest.temperature,
maxTokens: providerRequest.maxTokens,
apiKey: finalApiKey,
azureEndpoint: providerRequest.azureEndpoint,
azureApiVersion: providerRequest.azureApiVersion,
vertexProject: providerRequest.vertexProject,
vertexLocation: providerRequest.vertexLocation,
bedrockAccessKeyId: providerRequest.bedrockAccessKeyId,
bedrockSecretKey: providerRequest.bedrockSecretKey,
bedrockRegion: providerRequest.bedrockRegion,
responseFormat: providerRequest.responseFormat,
workflowId: providerRequest.workflowId,
workspaceId: ctx.workspaceId,
stream: providerRequest.stream,
messages: 'messages' in providerRequest ? providerRequest.messages : undefined,
environmentVariables: ctx.environmentVariables || {},
workflowVariables: ctx.workflowVariables || {},
blockData,
blockNameMapping,
isDeployedContext: ctx.isDeployedContext,
})
return this.processProviderResponse(response, block, responseFormat)
}
private async executeBrowserSide(
ctx: ExecutionContext,
providerRequest: any,
block: SerializedBlock,
responseFormat: any,
providerStartTime: number,
inputs: AgentInputs
) {
const url = buildAPIUrl('/api/providers')
const response = await fetch(url.toString(), {
method: 'POST',
headers: { 'Content-Type': HTTP.CONTENT_TYPE.JSON },
body: stringifyJSON(providerRequest),
signal: AbortSignal.timeout(AGENT.REQUEST_TIMEOUT),
})
if (!response.ok) {
const errorMessage = await extractAPIErrorMessage(response)
throw new Error(errorMessage)
}
const contentType = response.headers.get('Content-Type')
if (contentType?.includes(HTTP.CONTENT_TYPE.EVENT_STREAM)) {
return this.handleStreamingResponse(response, block, ctx, inputs)
}
const result = await response.json()
return this.processProviderResponse(result, block, responseFormat)
}
private async handleStreamingResponse(
response: Response,
block: SerializedBlock,
_ctx?: ExecutionContext,
_inputs?: AgentInputs
): Promise<StreamingExecution> {
const executionDataHeader = response.headers.get('X-Execution-Data')
if (executionDataHeader) {
try {
const executionData = JSON.parse(executionDataHeader)
return {
stream: response.body!,
execution: {
success: executionData.success,
output: executionData.output || {},
error: executionData.error,
logs: [],
metadata: executionData.metadata || {
duration: DEFAULTS.EXECUTION_TIME,
startTime: new Date().toISOString(),
},
isStreaming: true,
blockId: block.id,
blockName: block.metadata?.name,
blockType: block.metadata?.id,
} as any,
}
} catch (error) {
logger.error('Failed to parse execution data from header:', error)
}
}
return this.createMinimalStreamingExecution(response.body!)
}
/** /**
* Resolves a Vertex AI OAuth credential to an access token * Resolves a Vertex AI OAuth credential to an access token
*/ */

View File

@@ -16,6 +16,168 @@ export interface AuthResult {
error?: string error?: string
} }
/**
* Resolves userId from a verified internal JWT token.
* Extracts workflowId/userId from URL params or POST body, then looks up userId if needed.
*/
async function resolveUserFromJwt(
request: NextRequest,
verificationUserId: string | null,
options: { requireWorkflowId?: boolean }
): Promise<AuthResult> {
let workflowId: string | null = null
let userId: string | null = verificationUserId
const { searchParams } = new URL(request.url)
workflowId = searchParams.get('workflowId')
if (!userId) {
userId = searchParams.get('userId')
}
if (!workflowId && !userId && request.method === 'POST') {
try {
const clonedRequest = request.clone()
const bodyText = await clonedRequest.text()
if (bodyText) {
const body = JSON.parse(bodyText)
workflowId = body.workflowId || body._context?.workflowId
userId = userId || body.userId || body._context?.userId
}
} catch {
// Ignore JSON parse errors
}
}
if (userId) {
return { success: true, userId, authType: 'internal_jwt' }
}
if (workflowId) {
const [workflowData] = await db
.select({ userId: workflow.userId })
.from(workflow)
.where(eq(workflow.id, workflowId))
.limit(1)
if (!workflowData) {
return { success: false, error: 'Workflow not found' }
}
return { success: true, userId: workflowData.userId, authType: 'internal_jwt' }
}
if (options.requireWorkflowId !== false) {
return { success: false, error: 'workflowId or userId required for internal JWT calls' }
}
return { success: true, authType: 'internal_jwt' }
}
/**
* Check for internal JWT authentication only.
* Use this for routes that should ONLY be accessible by the executor (server-to-server).
* Rejects session and API key authentication.
*
* @param request - The incoming request
* @param options - Optional configuration
* @param options.requireWorkflowId - Whether workflowId/userId is required (default: true)
*/
export async function checkInternalAuth(
request: NextRequest,
options: { requireWorkflowId?: boolean } = {}
): Promise<AuthResult> {
try {
const authHeader = request.headers.get('authorization')
const apiKeyHeader = request.headers.get('x-api-key')
if (apiKeyHeader) {
return {
success: false,
error: 'API key access not allowed for this endpoint. Use workflow execution instead.',
}
}
if (!authHeader?.startsWith('Bearer ')) {
return {
success: false,
error: 'Internal authentication required',
}
}
const token = authHeader.split(' ')[1]
const verification = await verifyInternalToken(token)
if (!verification.valid) {
return { success: false, error: 'Invalid internal token' }
}
return resolveUserFromJwt(request, verification.userId || null, options)
} catch (error) {
logger.error('Error in internal authentication:', error)
return {
success: false,
error: 'Authentication error',
}
}
}
/**
* Check for session or internal JWT authentication.
* Use this for routes that should be accessible by the UI and executor,
* but NOT by external API keys.
*
* @param request - The incoming request
* @param options - Optional configuration
* @param options.requireWorkflowId - Whether workflowId/userId is required for JWT (default: true)
*/
export async function checkSessionOrInternalAuth(
request: NextRequest,
options: { requireWorkflowId?: boolean } = {}
): Promise<AuthResult> {
try {
// 1. Reject API keys first
const apiKeyHeader = request.headers.get('x-api-key')
if (apiKeyHeader) {
return {
success: false,
error: 'API key access not allowed for this endpoint',
}
}
// 2. Check for internal JWT token
const authHeader = request.headers.get('authorization')
if (authHeader?.startsWith('Bearer ')) {
const token = authHeader.split(' ')[1]
const verification = await verifyInternalToken(token)
if (verification.valid) {
return resolveUserFromJwt(request, verification.userId || null, options)
}
}
// 3. Try session auth (for web UI)
const session = await getSession()
if (session?.user?.id) {
return {
success: true,
userId: session.user.id,
authType: 'session',
}
}
return {
success: false,
error: 'Authentication required - provide session or internal JWT',
}
} catch (error) {
logger.error('Error in session/internal authentication:', error)
return {
success: false,
error: 'Authentication error',
}
}
}
/** /**
* Check for authentication using any of the 3 supported methods: * Check for authentication using any of the 3 supported methods:
* 1. Session authentication (cookies) * 1. Session authentication (cookies)
@@ -36,70 +198,7 @@ export async function checkHybridAuth(
const verification = await verifyInternalToken(token) const verification = await verifyInternalToken(token)
if (verification.valid) { if (verification.valid) {
let workflowId: string | null = null return resolveUserFromJwt(request, verification.userId || null, options)
let userId: string | null = verification.userId || null
const { searchParams } = new URL(request.url)
workflowId = searchParams.get('workflowId')
if (!userId) {
userId = searchParams.get('userId')
}
if (!workflowId && !userId && request.method === 'POST') {
try {
// Clone the request to avoid consuming the original body
const clonedRequest = request.clone()
const bodyText = await clonedRequest.text()
if (bodyText) {
const body = JSON.parse(bodyText)
workflowId = body.workflowId || body._context?.workflowId
userId = userId || body.userId || body._context?.userId
}
} catch {
// Ignore JSON parse errors
}
}
if (userId) {
return {
success: true,
userId,
authType: 'internal_jwt',
}
}
if (workflowId) {
const [workflowData] = await db
.select({ userId: workflow.userId })
.from(workflow)
.where(eq(workflow.id, workflowId))
.limit(1)
if (!workflowData) {
return {
success: false,
error: 'Workflow not found',
}
}
return {
success: true,
userId: workflowData.userId,
authType: 'internal_jwt',
}
}
if (options.requireWorkflowId !== false) {
return {
success: false,
error: 'workflowId or userId required for internal JWT calls',
}
}
return {
success: true,
authType: 'internal_jwt',
}
} }
} }

View File

@@ -2,3 +2,5 @@ export type { AnonymousSession } from './anonymous'
export { createAnonymousSession, ensureAnonymousUserExists } from './anonymous' export { createAnonymousSession, ensureAnonymousUserExists } from './anonymous'
export { auth, getSession, signIn, signUp } from './auth' export { auth, getSession, signIn, signUp } from './auth'
export { ANONYMOUS_USER, ANONYMOUS_USER_ID } from './constants' export { ANONYMOUS_USER, ANONYMOUS_USER_ID } from './constants'
export type { AuthResult } from './hybrid'
export { checkHybridAuth, checkInternalAuth, checkSessionOrInternalAuth } from './hybrid'