mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-24 14:27:56 -05:00
fix(security): restrict API key access on internal-only routes (#2964)
* fix(security): restrict API key access on internal-only routes * test(security): update function execute tests for checkInternalAuth * updated agent handler * move session check higher in checkSessionOrInternalAuth * extracted duplicate code into helper for resolving user from jwt
This commit is contained in:
@@ -85,10 +85,10 @@ vi.mock('@/lib/execution/isolated-vm', () => ({
|
||||
vi.mock('@sim/logger', () => loggerMock)
|
||||
|
||||
vi.mock('@/lib/auth/hybrid', () => ({
|
||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
||||
checkInternalAuth: vi.fn().mockResolvedValue({
|
||||
success: true,
|
||||
userId: 'user-123',
|
||||
authType: 'session',
|
||||
authType: 'internal_jwt',
|
||||
}),
|
||||
}))
|
||||
|
||||
@@ -119,8 +119,8 @@ describe('Function Execute API Route', () => {
|
||||
|
||||
describe('Security Tests', () => {
|
||||
it('should reject unauthorized requests', async () => {
|
||||
const { checkHybridAuth } = await import('@/lib/auth/hybrid')
|
||||
vi.mocked(checkHybridAuth).mockResolvedValueOnce({
|
||||
const { checkInternalAuth } = await import('@/lib/auth/hybrid')
|
||||
vi.mocked(checkInternalAuth).mockResolvedValueOnce({
|
||||
success: false,
|
||||
error: 'Unauthorized',
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
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 { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { executeInE2B } from '@/lib/execution/e2b'
|
||||
@@ -582,7 +582,7 @@ export async function POST(req: NextRequest) {
|
||||
let resolvedCode = '' // Store resolved code for error reporting
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(req)
|
||||
const auth = await checkInternalAuth(req)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized function execution attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -3,7 +3,7 @@ import { account } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { eq } from 'drizzle-orm'
|
||||
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 { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils'
|
||||
import { refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const startTime = Date.now()
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const auth = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
if (!auth.success || !auth.userId) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ describe('Custom Tools API Routes', () => {
|
||||
}))
|
||||
|
||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
||||
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||
success: true,
|
||||
userId: 'user-123',
|
||||
authType: 'session',
|
||||
@@ -254,7 +254,7 @@ describe('Custom Tools API Routes', () => {
|
||||
)
|
||||
|
||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
||||
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||
success: false,
|
||||
error: 'Unauthorized',
|
||||
}),
|
||||
@@ -304,7 +304,7 @@ describe('Custom Tools API Routes', () => {
|
||||
describe('POST /api/tools/custom', () => {
|
||||
it('should reject unauthorized requests', async () => {
|
||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
||||
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||
success: false,
|
||||
error: 'Unauthorized',
|
||||
}),
|
||||
@@ -390,7 +390,7 @@ describe('Custom Tools API Routes', () => {
|
||||
|
||||
it('should prevent unauthorized deletion of user-scoped tool', async () => {
|
||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
||||
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||
success: true,
|
||||
userId: 'user-456',
|
||||
authType: 'session',
|
||||
@@ -413,7 +413,7 @@ describe('Custom Tools API Routes', () => {
|
||||
|
||||
it('should reject unauthorized requests', async () => {
|
||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
||||
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||
success: false,
|
||||
error: 'Unauthorized',
|
||||
}),
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { and, desc, eq, isNull, or } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { upsertCustomTools } from '@/lib/workflows/custom-tools/operations'
|
||||
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
|
||||
@@ -42,8 +42,8 @@ export async function GET(request: NextRequest) {
|
||||
const workflowId = searchParams.get('workflowId')
|
||||
|
||||
try {
|
||||
// Use hybrid auth to support session, API key, and internal JWT
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
// Use session/internal auth to support session and internal JWT (no API key access)
|
||||
const authResult = await checkSessionOrInternalAuth(request, { requireWorkflowId: false })
|
||||
if (!authResult.success || !authResult.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized custom tools access attempt`)
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
@@ -69,8 +69,8 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
// Check workspace permissions
|
||||
// For internal JWT with workflowId: checkHybridAuth already resolved userId from workflow owner
|
||||
// For session/API key: verify user has access to the workspace
|
||||
// For internal JWT with workflowId: checkSessionOrInternalAuth already resolved userId from workflow owner
|
||||
// For session: verify user has access to the workspace
|
||||
// For legacy (no workspaceId): skip workspace check, rely on userId match
|
||||
if (resolvedWorkspaceId && !(authResult.authType === 'internal_jwt' && workflowId)) {
|
||||
const userPermission = await getUserEntityPermissions(
|
||||
@@ -116,8 +116,8 @@ export async function POST(req: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
// Use hybrid auth (though this endpoint is only called from UI)
|
||||
const authResult = await checkHybridAuth(req, { requireWorkflowId: false })
|
||||
// Use session/internal auth (no API key access)
|
||||
const authResult = await checkSessionOrInternalAuth(req, { requireWorkflowId: false })
|
||||
if (!authResult.success || !authResult.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized custom tools update attempt`)
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
@@ -193,8 +193,8 @@ export async function DELETE(request: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
// Use hybrid auth (though this endpoint is only called from UI)
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
// Use session/internal auth (no API key access)
|
||||
const authResult = await checkSessionOrInternalAuth(request, { requireWorkflowId: false })
|
||||
if (!authResult.success || !authResult.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized custom tool deletion attempt`)
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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 { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Discord send attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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 { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail add label attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail archive attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail delete attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail draft attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail mark read attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail mark unread attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail move attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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 { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail remove label attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail send attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Gmail unarchive attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -56,7 +56,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Google Drive upload attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
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 { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
@@ -15,7 +15,7 @@ export async function GET(request: NextRequest) {
|
||||
const imageUrl = url.searchParams.get('url')
|
||||
const requestId = generateRequestId()
|
||||
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
if (!authResult.success) {
|
||||
logger.error(`[${requestId}] Authentication failed for image proxy:`, authResult.error)
|
||||
return new NextResponse('Unauthorized', { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { Resend } from 'resend'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized mail send attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Teams chat delete attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Teams channel write attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Teams chat write attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { StorageService } from '@/lib/uploads'
|
||||
@@ -30,7 +30,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success || !authResult.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized Mistral parse attempt`, {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('MySQLDeleteAPI')
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized MySQL delete attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('MySQLExecuteAPI')
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized MySQL execute attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('MySQLInsertAPI')
|
||||
@@ -43,7 +43,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized MySQL insert attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('MySQLIntrospectAPI')
|
||||
@@ -20,7 +20,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized MySQL introspect attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('MySQLQueryAPI')
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized MySQL query attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('MySQLUpdateAPI')
|
||||
@@ -41,7 +41,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized MySQL update attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import * as XLSX from 'xlsx'
|
||||
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 { generateRequestId } from '@/lib/core/utils/request'
|
||||
import {
|
||||
@@ -39,7 +39,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized OneDrive upload attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Outlook copy attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Outlook delete attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Outlook draft attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Outlook mark read attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Outlook mark unread attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Outlook move attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Outlook send attempt: ${authResult.error}`)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('PostgreSQLDeleteAPI')
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL delete attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
createPostgresConnection,
|
||||
executeQuery,
|
||||
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL execute attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('PostgreSQLInsertAPI')
|
||||
@@ -43,7 +43,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL insert attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('PostgreSQLIntrospectAPI')
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL introspect attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('PostgreSQLQueryAPI')
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL query attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('PostgreSQLUpdateAPI')
|
||||
@@ -41,7 +41,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL update attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { StorageService } from '@/lib/uploads'
|
||||
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success || !authResult.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized Pulse parse attempt`, {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { StorageService } from '@/lib/uploads'
|
||||
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success || !authResult.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized Reducto parse attempt`, {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CopyObjectCommand, type ObjectCannedACL, S3Client } from '@aws-sdk/clie
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -24,7 +24,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized S3 copy object attempt: ${authResult.error}`)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized S3 delete object attempt: ${authResult.error}`)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ListObjectsV2Command, S3Client } from '@aws-sdk/client-s3'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized S3 list objects attempt: ${authResult.error}`)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type ObjectCannedACL, PutObjectCommand, S3Client } from '@aws-sdk/clien
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized S3 put object attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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 { env } from '@/lib/core/config/env'
|
||||
import { executeTool } from '@/tools'
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const { searchParams: urlParams } = new URL(request.url)
|
||||
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) {
|
||||
const errorMessage = workflowId ? 'Workflow not found' : authResult.error || 'Unauthorized'
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import type { SFTPWrapper } from 'ssh2'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import {
|
||||
createSftpConnection,
|
||||
@@ -72,7 +72,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized SFTP delete attempt: ${authResult.error}`)
|
||||
|
||||
@@ -2,7 +2,7 @@ import path from 'path'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { createSftpConnection, getSftp, isPathSafe, sanitizePath } from '@/app/api/tools/sftp/utils'
|
||||
|
||||
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized SFTP download attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import {
|
||||
createSftpConnection,
|
||||
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized SFTP list attempt: ${authResult.error}`)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import type { SFTPWrapper } from 'ssh2'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import {
|
||||
createSftpConnection,
|
||||
@@ -60,7 +60,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized SFTP mkdir attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -44,7 +44,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized SFTP upload attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized SharePoint upload attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
@@ -13,7 +13,7 @@ const SlackAddReactionSchema = z.object({
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
@@ -12,7 +12,7 @@ const SlackDeleteMessageSchema = z.object({
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
return NextResponse.json(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { openDMChannel } from '../utils'
|
||||
|
||||
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Slack read messages attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { sendSlackMessage } from '../utils'
|
||||
|
||||
@@ -26,7 +26,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Slack send attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Slack update message attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { env } from '@/lib/core/config/env'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { type SMSOptions, sendSMS } from '@/lib/messaging/sms/service'
|
||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized SMS send attempt: ${authResult.error}`)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import nodemailer from 'nodemailer'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized SMTP send attempt: ${authResult.error}`)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('SSHCheckCommandExistsAPI')
|
||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH check command exists attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import type { Client, SFTPWrapper, Stats } from 'ssh2'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
createSSHConnection,
|
||||
getFileType,
|
||||
@@ -40,7 +40,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH check file exists attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
createSSHConnection,
|
||||
escapeShellArg,
|
||||
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH create directory attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
createSSHConnection,
|
||||
escapeShellArg,
|
||||
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH delete file attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import type { Client, SFTPWrapper } from 'ssh2'
|
||||
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'
|
||||
|
||||
const logger = createLogger('SSHDownloadFileAPI')
|
||||
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH download file attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('SSHExecuteCommandAPI')
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH execute command attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('SSHExecuteScriptAPI')
|
||||
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH execute script attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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'
|
||||
|
||||
const logger = createLogger('SSHGetSystemInfoAPI')
|
||||
@@ -20,7 +20,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH get system info attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import type { Client, FileEntry, SFTPWrapper } from 'ssh2'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
createSSHConnection,
|
||||
getFileType,
|
||||
@@ -61,7 +61,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH list directory attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
createSSHConnection,
|
||||
escapeShellArg,
|
||||
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH move/rename attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import type { Client, SFTPWrapper } from 'ssh2'
|
||||
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'
|
||||
|
||||
const logger = createLogger('SSHReadFileContentAPI')
|
||||
@@ -36,7 +36,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH read file content attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import type { Client, SFTPWrapper } from 'ssh2'
|
||||
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'
|
||||
|
||||
const logger = createLogger('SSHUploadFileAPI')
|
||||
@@ -38,7 +38,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH upload file attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import type { Client, SFTPWrapper } from 'ssh2'
|
||||
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'
|
||||
|
||||
const logger = createLogger('SSHWriteFileContentAPI')
|
||||
@@ -37,7 +37,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
try {
|
||||
const auth = await checkHybridAuth(request)
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized SSH write file content attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
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 type { UserFile } from '@/executor/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`)
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
if (!authResult.success) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, {
|
||||
const authResult = await checkInternalAuth(request, {
|
||||
requireWorkflowId: false,
|
||||
})
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import crypto from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
validateAwsRegion,
|
||||
validateExternalUrl,
|
||||
@@ -292,7 +292,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success || !authResult.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized Textract parse attempt`, {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { NextRequest } 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 { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { StorageService } from '@/lib/uploads'
|
||||
@@ -10,7 +10,7 @@ const logger = createLogger('ProxyTTSAPI')
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
if (!authResult.success) {
|
||||
logger.error('Authentication failed for TTS proxy:', authResult.error)
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import type { NextRequest } 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 { getBaseUrl } from '@/lib/core/utils/urls'
|
||||
import { StorageService } from '@/lib/uploads'
|
||||
@@ -87,7 +87,7 @@ export async function POST(request: NextRequest) {
|
||||
logger.info(`[${requestId}] TTS unified request started`)
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
if (!authResult.success) {
|
||||
logger.error('Authentication failed for TTS unified proxy:', authResult.error)
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
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 type { UserFile } from '@/executor/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`)
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
if (!authResult.success) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized Vision analyze attempt: ${authResult.error}`)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { generateRequestId } from '@/lib/core/utils/request'
|
||||
import {
|
||||
getFileExtension,
|
||||
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
|
||||
const requestId = generateRequestId()
|
||||
|
||||
try {
|
||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
||||
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||
|
||||
if (!authResult.success) {
|
||||
logger.warn(`[${requestId}] Unauthorized WordPress upload attempt: ${authResult.error}`)
|
||||
|
||||
@@ -144,25 +144,22 @@ describe('AgentBlockHandler', () => {
|
||||
}
|
||||
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({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
if (name === 'Content-Type') return 'application/json'
|
||||
if (name === 'X-Execution-Data') return null
|
||||
return null
|
||||
},
|
||||
get: () => null,
|
||||
},
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
content: 'Mocked response content',
|
||||
model: 'mock-model',
|
||||
tokens: { input: 10, output: 20, total: 30 },
|
||||
toolCalls: [],
|
||||
cost: 0.001,
|
||||
timing: { total: 100 },
|
||||
}),
|
||||
json: () => Promise.resolve({}),
|
||||
})
|
||||
})
|
||||
|
||||
@@ -244,7 +241,7 @@ describe('AgentBlockHandler', () => {
|
||||
const result = await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
expect(mockGetProviderFromModel).toHaveBeenCalledWith('gpt-4o')
|
||||
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object))
|
||||
expect(mockExecuteProviderRequest).toHaveBeenCalled()
|
||||
expect(result).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
@@ -263,34 +260,21 @@ describe('AgentBlockHandler', () => {
|
||||
return result
|
||||
})
|
||||
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
if (name === 'Content-Type') return 'application/json'
|
||||
if (name === 'X-Execution-Data') return null
|
||||
return null
|
||||
},
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
content: 'Using tools to respond',
|
||||
model: 'mock-model',
|
||||
tokens: { input: 10, output: 20, total: 30 },
|
||||
toolCalls: [
|
||||
{
|
||||
name: 'auto_tool',
|
||||
arguments: { input: 'test input for auto tool' },
|
||||
},
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
content: 'Using tools to respond',
|
||||
model: 'mock-model',
|
||||
tokens: { input: 10, output: 20, total: 30 },
|
||||
toolCalls: [
|
||||
{
|
||||
name: 'auto_tool',
|
||||
arguments: { input: 'test input for auto tool' },
|
||||
},
|
||||
{
|
||||
name: 'force_tool',
|
||||
arguments: { input: 'test input for force tool' },
|
||||
},
|
||||
],
|
||||
timing: { total: 100 },
|
||||
}),
|
||||
})
|
||||
{
|
||||
name: 'force_tool',
|
||||
arguments: { input: 'test input for force tool' },
|
||||
},
|
||||
],
|
||||
timing: { total: 100 },
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -403,8 +387,8 @@ describe('AgentBlockHandler', () => {
|
||||
expect.any(Object) // execution context
|
||||
)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
expect(requestBody.tools.length).toBe(2)
|
||||
})
|
||||
@@ -443,8 +427,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
expect(requestBody.tools.length).toBe(2)
|
||||
|
||||
@@ -488,8 +472,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
expect(requestBody.tools[0].usageControl).toBe('auto')
|
||||
expect(requestBody.tools[1].usageControl).toBe('force')
|
||||
@@ -553,8 +537,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
expect(requestBody.tools.length).toBe(2)
|
||||
|
||||
@@ -583,7 +567,7 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
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 () => {
|
||||
@@ -625,7 +609,7 @@ describe('AgentBlockHandler', () => {
|
||||
inputs.tools[0],
|
||||
expect.objectContaining({ selectedOperation: 'analyze' })
|
||||
)
|
||||
expect(mockFetch).toHaveBeenCalledWith(expect.any(String), expect.any(Object))
|
||||
expect(mockExecuteProviderRequest).toHaveBeenCalled()
|
||||
expect(result).toEqual(expectedOutput)
|
||||
})
|
||||
|
||||
@@ -676,30 +660,17 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
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 () => {
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
if (name === 'Content-Type') return 'application/json'
|
||||
if (name === 'X-Execution-Data') return null
|
||||
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,
|
||||
}),
|
||||
})
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
content: '{"result": "Success", "score": 0.95}',
|
||||
model: 'mock-model',
|
||||
tokens: { input: 10, output: 20, total: 30 },
|
||||
timing: { total: 100 },
|
||||
toolCalls: [],
|
||||
cost: undefined,
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -723,24 +694,11 @@ describe('AgentBlockHandler', () => {
|
||||
})
|
||||
|
||||
it('should handle responseFormat when it is an empty string', async () => {
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
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 },
|
||||
}),
|
||||
})
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
content: 'Regular text response',
|
||||
model: 'mock-model',
|
||||
tokens: { input: 10, output: 20, total: 30 },
|
||||
timing: { total: 100 },
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -763,26 +721,13 @@ describe('AgentBlockHandler', () => {
|
||||
})
|
||||
|
||||
it('should handle invalid JSON in responseFormat gracefully', async () => {
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
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 },
|
||||
toolCalls: [],
|
||||
cost: undefined,
|
||||
}),
|
||||
})
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
content: 'Regular text response',
|
||||
model: 'mock-model',
|
||||
tokens: { input: 10, output: 20, total: 30 },
|
||||
timing: { total: 100 },
|
||||
toolCalls: [],
|
||||
cost: undefined,
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -806,26 +751,13 @@ describe('AgentBlockHandler', () => {
|
||||
})
|
||||
|
||||
it('should handle variable references in responseFormat gracefully', async () => {
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
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 },
|
||||
toolCalls: [],
|
||||
cost: undefined,
|
||||
}),
|
||||
})
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
content: 'Regular text response',
|
||||
model: 'mock-model',
|
||||
tokens: { input: 10, output: 20, total: 30 },
|
||||
timing: { total: 100 },
|
||||
toolCalls: [],
|
||||
cost: undefined,
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -856,7 +788,7 @@ describe('AgentBlockHandler', () => {
|
||||
}
|
||||
|
||||
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(
|
||||
'Provider API Error'
|
||||
@@ -870,30 +802,17 @@ describe('AgentBlockHandler', () => {
|
||||
},
|
||||
})
|
||||
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
if (name === 'Content-Type') return 'application/json'
|
||||
if (name === 'X-Execution-Data') return null
|
||||
return null
|
||||
},
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
stream: mockStreamBody,
|
||||
execution: {
|
||||
success: true,
|
||||
output: {},
|
||||
logs: [],
|
||||
metadata: {
|
||||
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 = {
|
||||
@@ -947,22 +866,9 @@ describe('AgentBlockHandler', () => {
|
||||
},
|
||||
}
|
||||
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
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,
|
||||
}),
|
||||
})
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
stream: mockStreamBody,
|
||||
execution: mockExecutionData,
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -996,30 +902,21 @@ describe('AgentBlockHandler', () => {
|
||||
},
|
||||
})
|
||||
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => (name === 'Content-Type' ? 'application/json' : null),
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
stream: {}, // Serialized stream placeholder
|
||||
execution: {
|
||||
success: true,
|
||||
output: {
|
||||
content: 'Test streaming content',
|
||||
model: 'gpt-4o',
|
||||
tokens: { input: 10, output: 5, total: 15 },
|
||||
},
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
stream: {}, // Serialized stream placeholder
|
||||
execution: {
|
||||
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,
|
||||
},
|
||||
},
|
||||
}),
|
||||
})
|
||||
logs: [],
|
||||
metadata: {
|
||||
startTime: new Date().toISOString(),
|
||||
duration: 150,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -1060,8 +957,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Verify messages were built correctly
|
||||
expect(requestBody.messages).toBeDefined()
|
||||
@@ -1110,8 +1007,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Verify messages were built correctly
|
||||
expect(requestBody.messages).toBeDefined()
|
||||
@@ -1149,8 +1046,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Verify messages were built correctly
|
||||
expect(requestBody.messages).toBeDefined()
|
||||
@@ -1181,8 +1078,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Verify messages were built correctly
|
||||
// Agent system (1) + legacy memories (3) + user from messages (1) = 5
|
||||
@@ -1225,8 +1122,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Verify messages were built correctly
|
||||
expect(requestBody.messages).toBeDefined()
|
||||
@@ -1268,8 +1165,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Verify messages were built correctly
|
||||
expect(requestBody.messages).toBeDefined()
|
||||
@@ -1310,8 +1207,8 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
const fetchCall = mockFetch.mock.calls[0]
|
||||
const requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Verify user prompt content was extracted correctly
|
||||
expect(requestBody.messages).toBeDefined()
|
||||
@@ -1337,15 +1234,14 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
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 requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
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.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.apiKey).toBe('test-azure-api-key')
|
||||
})
|
||||
@@ -1365,15 +1261,14 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
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 requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Check that GPT-5 parameters are included in the request
|
||||
expect(requestBody.reasoningEffort).toBe('minimal')
|
||||
expect(requestBody.verbosity).toBe('high')
|
||||
expect(requestBody.provider).toBe('openai')
|
||||
expect(providerCall[0]).toBe('openai')
|
||||
expect(requestBody.model).toBe('gpt-5')
|
||||
expect(requestBody.apiKey).toBe('test-api-key')
|
||||
})
|
||||
@@ -1385,22 +1280,20 @@ describe('AgentBlockHandler', () => {
|
||||
userPrompt: 'Hello!',
|
||||
apiKey: 'test-api-key',
|
||||
temperature: 0.7,
|
||||
// No reasoningEffort or verbosity provided
|
||||
}
|
||||
|
||||
mockGetProviderFromModel.mockReturnValue('openai')
|
||||
|
||||
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 requestBody = JSON.parse(fetchCall[1].body)
|
||||
const providerCall = mockExecuteProviderRequest.mock.calls[0]
|
||||
const requestBody = providerCall[1]
|
||||
|
||||
// Check that GPT-5 parameters are undefined when not provided
|
||||
expect(requestBody.reasoningEffort).toBeUndefined()
|
||||
expect(requestBody.verbosity).toBeUndefined()
|
||||
expect(requestBody.provider).toBe('openai')
|
||||
expect(providerCall[0]).toBe('openai')
|
||||
expect(requestBody.model).toBe('gpt-5')
|
||||
})
|
||||
|
||||
@@ -1422,42 +1315,29 @@ describe('AgentBlockHandler', () => {
|
||||
return Promise.resolve({ success: false, error: 'Unknown tool' })
|
||||
})
|
||||
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
if (name === 'Content-Type') return 'application/json'
|
||||
if (name === 'X-Execution-Data') return null
|
||||
return null
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
content: 'I will use MCP tools to help you.',
|
||||
model: 'gpt-4o',
|
||||
tokens: { input: 15, output: 25, total: 40 },
|
||||
toolCalls: [
|
||||
{
|
||||
name: 'mcp-server1-list_files',
|
||||
arguments: { path: '/tmp' },
|
||||
result: {
|
||||
success: true,
|
||||
output: { content: [{ type: 'text', text: 'Files listed' }] },
|
||||
},
|
||||
},
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
content: 'I will use MCP tools to help you.',
|
||||
model: 'gpt-4o',
|
||||
tokens: { input: 15, output: 25, total: 40 },
|
||||
toolCalls: [
|
||||
{
|
||||
name: 'mcp-server1-list_files',
|
||||
arguments: { path: '/tmp' },
|
||||
result: {
|
||||
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 },
|
||||
}),
|
||||
})
|
||||
{
|
||||
name: 'mcp-server2-search',
|
||||
arguments: { query: 'test', limit: 5 },
|
||||
result: {
|
||||
success: true,
|
||||
output: { content: [{ type: 'text', text: 'Search results' }] },
|
||||
},
|
||||
},
|
||||
],
|
||||
timing: { total: 150 },
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -1533,34 +1413,21 @@ describe('AgentBlockHandler', () => {
|
||||
return Promise.resolve({ success: false, error: 'Unknown tool' })
|
||||
})
|
||||
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
if (name === 'Content-Type') return 'application/json'
|
||||
if (name === 'X-Execution-Data') return null
|
||||
return null
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
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',
|
||||
},
|
||||
},
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
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 },
|
||||
}),
|
||||
})
|
||||
],
|
||||
timing: { total: 100 },
|
||||
})
|
||||
|
||||
const inputs = {
|
||||
@@ -1638,25 +1505,12 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
mockGetProviderFromModel.mockReturnValue('openai')
|
||||
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => {
|
||||
if (name === 'Content-Type') return 'application/json'
|
||||
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 },
|
||||
}),
|
||||
})
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
content: 'Used MCP tools successfully',
|
||||
model: 'gpt-4o',
|
||||
tokens: { input: 20, output: 30, total: 50 },
|
||||
toolCalls: [],
|
||||
timing: { total: 200 },
|
||||
})
|
||||
|
||||
mockTransformBlockTool.mockImplementation((tool: any) => ({
|
||||
@@ -1669,11 +1523,9 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
const result = await handler.execute(mockContext, mockBlock, inputs)
|
||||
|
||||
// Verify that the agent executed successfully with MCP tools
|
||||
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).model).toBe('gpt-4o')
|
||||
})
|
||||
@@ -1691,21 +1543,12 @@ describe('AgentBlockHandler', () => {
|
||||
return Promise.resolve({ success: false, error: 'Unknown tool' })
|
||||
})
|
||||
|
||||
mockFetch.mockImplementationOnce(() => {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => (name === 'Content-Type' ? 'application/json' : null),
|
||||
},
|
||||
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 },
|
||||
}),
|
||||
})
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
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 = {
|
||||
@@ -1815,37 +1658,26 @@ describe('AgentBlockHandler', () => {
|
||||
const discoveryCalls = fetchCalls.filter((c) => c.url.includes('/api/mcp/tools/discover'))
|
||||
expect(discoveryCalls.length).toBe(0)
|
||||
|
||||
const providerCalls = fetchCalls.filter((c) => c.url.includes('/api/providers'))
|
||||
expect(providerCalls.length).toBe(1)
|
||||
expect(mockExecuteProviderRequest).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should pass toolSchema to execution endpoint when using cached schema', async () => {
|
||||
let executionCall: any = null
|
||||
|
||||
mockFetch.mockImplementation((url: string, options: any) => {
|
||||
if (url.includes('/api/providers')) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
headers: {
|
||||
get: (name: string) => (name === 'Content-Type' ? 'application/json' : null),
|
||||
},
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
content: 'Tool executed',
|
||||
model: 'gpt-4o',
|
||||
tokens: { input: 10, output: 10, total: 20 },
|
||||
toolCalls: [
|
||||
{
|
||||
name: 'search_files',
|
||||
arguments: { query: 'test' },
|
||||
result: { success: true, output: {} },
|
||||
},
|
||||
],
|
||||
timing: { total: 50 },
|
||||
}),
|
||||
})
|
||||
}
|
||||
mockExecuteProviderRequest.mockResolvedValueOnce({
|
||||
content: 'Tool executed',
|
||||
model: 'gpt-4o',
|
||||
tokens: { input: 10, output: 10, total: 20 },
|
||||
toolCalls: [
|
||||
{
|
||||
name: 'search_files',
|
||||
arguments: JSON.stringify({ query: 'test' }),
|
||||
},
|
||||
],
|
||||
timing: { total: 50 },
|
||||
})
|
||||
|
||||
mockFetch.mockImplementation((url: string, options: any) => {
|
||||
if (url.includes('/api/mcp/tools/execute')) {
|
||||
executionCall = { url, body: JSON.parse(options.body) }
|
||||
return Promise.resolve({
|
||||
@@ -1898,13 +1730,11 @@ describe('AgentBlockHandler', () => {
|
||||
|
||||
await handler.execute(contextWithWorkspace, mockBlock, inputs)
|
||||
|
||||
const providerCalls = mockFetch.mock.calls.filter((c: any) => c[0].includes('/api/providers'))
|
||||
expect(providerCalls.length).toBe(1)
|
||||
|
||||
const providerRequestBody = JSON.parse(providerCalls[0][1].body)
|
||||
expect(providerRequestBody.tools).toBeDefined()
|
||||
expect(providerRequestBody.tools.length).toBe(1)
|
||||
expect(providerRequestBody.tools[0].name).toBe('search_files')
|
||||
expect(mockExecuteProviderRequest).toHaveBeenCalled()
|
||||
const providerCallArgs = mockExecuteProviderRequest.mock.calls[0]
|
||||
expect(providerCallArgs[1].tools).toBeDefined()
|
||||
expect(providerCallArgs[1].tools.length).toBe(1)
|
||||
expect(providerCallArgs[1].tools[0].name).toBe('search_files')
|
||||
})
|
||||
|
||||
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'))
|
||||
expect(discoveryCalls.length).toBe(0)
|
||||
|
||||
const providerCalls = fetchCalls.filter((c) => c.url.includes('/api/providers'))
|
||||
expect(providerCalls.length).toBe(1)
|
||||
|
||||
const providerRequestBody = JSON.parse(providerCalls[0].options.body)
|
||||
expect(providerRequestBody.tools.length).toBe(3)
|
||||
expect(mockExecuteProviderRequest).toHaveBeenCalled()
|
||||
const providerCallArgs = mockExecuteProviderRequest.mock.calls[0]
|
||||
expect(providerCallArgs[1].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[] = []
|
||||
|
||||
mockFetch.mockImplementation((url: string, options: any) => {
|
||||
|
||||
@@ -6,14 +6,7 @@ import { createMcpToolId } from '@/lib/mcp/utils'
|
||||
import { refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||
import { getAllBlocks } from '@/blocks'
|
||||
import type { BlockOutput } from '@/blocks/types'
|
||||
import {
|
||||
AGENT,
|
||||
BlockType,
|
||||
DEFAULTS,
|
||||
HTTP,
|
||||
REFERENCE,
|
||||
stripCustomToolPrefix,
|
||||
} from '@/executor/constants'
|
||||
import { AGENT, BlockType, DEFAULTS, REFERENCE, stripCustomToolPrefix } from '@/executor/constants'
|
||||
import { memoryService } from '@/executor/handlers/agent/memory'
|
||||
import type {
|
||||
AgentInputs,
|
||||
@@ -23,7 +16,7 @@ import type {
|
||||
} from '@/executor/handlers/agent/types'
|
||||
import type { BlockHandler, ExecutionContext, StreamingExecution } from '@/executor/types'
|
||||
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 {
|
||||
validateBlockType,
|
||||
@@ -52,11 +45,9 @@ export class AgentBlockHandler implements BlockHandler {
|
||||
block: SerializedBlock,
|
||||
inputs: AgentInputs
|
||||
): 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 filteredInputs = { ...inputs, tools: filteredTools }
|
||||
|
||||
// Validate tool permissions before processing
|
||||
await this.validateToolPermissions(ctx, filteredInputs.tools || [])
|
||||
|
||||
const responseFormat = this.parseResponseFormat(filteredInputs.responseFormat)
|
||||
@@ -80,13 +71,7 @@ export class AgentBlockHandler implements BlockHandler {
|
||||
streaming: streamingConfig.shouldUseStreaming ?? false,
|
||||
})
|
||||
|
||||
const result = await this.executeProviderRequest(
|
||||
ctx,
|
||||
providerRequest,
|
||||
block,
|
||||
responseFormat,
|
||||
filteredInputs
|
||||
)
|
||||
const result = await this.executeProviderRequest(ctx, providerRequest, block, responseFormat)
|
||||
|
||||
if (this.isStreamingExecution(result)) {
|
||||
if (filteredInputs.memoryType && filteredInputs.memoryType !== 'none') {
|
||||
@@ -996,157 +981,60 @@ export class AgentBlockHandler implements BlockHandler {
|
||||
ctx: ExecutionContext,
|
||||
providerRequest: any,
|
||||
block: SerializedBlock,
|
||||
responseFormat: any,
|
||||
inputs: AgentInputs
|
||||
responseFormat: any
|
||||
): Promise<BlockOutput | StreamingExecution> {
|
||||
const providerId = providerRequest.provider
|
||||
const model = providerRequest.model
|
||||
const providerStartTime = Date.now()
|
||||
|
||||
try {
|
||||
const isBrowser = typeof window !== 'undefined'
|
||||
let finalApiKey: string | undefined = providerRequest.apiKey
|
||||
|
||||
if (!isBrowser) {
|
||||
return this.executeServerSide(
|
||||
ctx,
|
||||
providerRequest,
|
||||
providerId,
|
||||
model,
|
||||
block,
|
||||
responseFormat,
|
||||
providerStartTime
|
||||
if (providerId === 'vertex' && providerRequest.vertexCredential) {
|
||||
finalApiKey = await this.resolveVertexCredential(
|
||||
providerRequest.vertexCredential,
|
||||
ctx.workflowId
|
||||
)
|
||||
}
|
||||
return this.executeBrowserSide(
|
||||
ctx,
|
||||
providerRequest,
|
||||
block,
|
||||
responseFormat,
|
||||
providerStartTime,
|
||||
inputs
|
||||
)
|
||||
|
||||
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,
|
||||
reasoningEffort: providerRequest.reasoningEffort,
|
||||
verbosity: providerRequest.verbosity,
|
||||
})
|
||||
|
||||
return this.processProviderResponse(response, block, responseFormat)
|
||||
} catch (error) {
|
||||
this.handleExecutionError(error, providerStartTime, providerId, model, ctx, block)
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,168 @@ export interface AuthResult {
|
||||
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:
|
||||
* 1. Session authentication (cookies)
|
||||
@@ -36,70 +198,7 @@ export async function checkHybridAuth(
|
||||
const verification = await verifyInternalToken(token)
|
||||
|
||||
if (verification.valid) {
|
||||
let workflowId: string | null = null
|
||||
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',
|
||||
}
|
||||
return resolveUserFromJwt(request, verification.userId || null, options)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,3 +2,5 @@ export type { AnonymousSession } from './anonymous'
|
||||
export { createAnonymousSession, ensureAnonymousUserExists } from './anonymous'
|
||||
export { auth, getSession, signIn, signUp } from './auth'
|
||||
export { ANONYMOUS_USER, ANONYMOUS_USER_ID } from './constants'
|
||||
export type { AuthResult } from './hybrid'
|
||||
export { checkHybridAuth, checkInternalAuth, checkSessionOrInternalAuth } from './hybrid'
|
||||
|
||||
Reference in New Issue
Block a user