mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-24 22:38:00 -05:00
Compare commits
12 Commits
fix/hitl
...
fix/copilo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d28c357b9 | ||
|
|
6ca36dd96e | ||
|
|
0275e54d26 | ||
|
|
2b5fb1da07 | ||
|
|
68683258c3 | ||
|
|
fc7f56e21b | ||
|
|
8429040921 | ||
|
|
8574e6c71f | ||
|
|
9c3e663cd8 | ||
|
|
48adaa00d8 | ||
|
|
211a7ac3a4 | ||
|
|
0f9b6ad1d2 |
@@ -124,11 +124,44 @@ Choose between four types of loops:
|
|||||||
3. Drag other blocks inside the loop container
|
3. Drag other blocks inside the loop container
|
||||||
4. Connect the blocks as needed
|
4. Connect the blocks as needed
|
||||||
|
|
||||||
### Accessing Results
|
### Referencing Loop Data
|
||||||
|
|
||||||
After a loop completes, you can access aggregated results:
|
There's an important distinction between referencing loop data from **inside** vs **outside** the loop:
|
||||||
|
|
||||||
- **`<loop.results>`**: Array of results from all loop iterations
|
<Tabs items={['Inside the Loop', 'Outside the Loop']}>
|
||||||
|
<Tab>
|
||||||
|
**Inside the loop**, use `<loop.>` references to access the current iteration context:
|
||||||
|
|
||||||
|
- **`<loop.index>`**: Current iteration number (0-based)
|
||||||
|
- **`<loop.currentItem>`**: Current item being processed (forEach only)
|
||||||
|
- **`<loop.items>`**: Full collection being iterated (forEach only)
|
||||||
|
|
||||||
|
```
|
||||||
|
// Inside a Function block within the loop
|
||||||
|
const idx = <loop.index>; // 0, 1, 2, ...
|
||||||
|
const item = <loop.currentItem>; // Current item
|
||||||
|
```
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
These references are only available for blocks **inside** the loop container. They give you access to the current iteration's context.
|
||||||
|
</Callout>
|
||||||
|
</Tab>
|
||||||
|
<Tab>
|
||||||
|
**Outside the loop** (after it completes), reference the loop block by its name to access aggregated results:
|
||||||
|
|
||||||
|
- **`<LoopBlockName.results>`**: Array of results from all iterations
|
||||||
|
|
||||||
|
```
|
||||||
|
// If your loop block is named "Process Items"
|
||||||
|
const allResults = <processitems.results>;
|
||||||
|
// Returns: [result1, result2, result3, ...]
|
||||||
|
```
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
After the loop completes, use the loop's block name (not `loop.`) to access the collected results. The block name is normalized (lowercase, no spaces).
|
||||||
|
</Callout>
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
## Example Use Cases
|
## Example Use Cases
|
||||||
|
|
||||||
@@ -184,28 +217,29 @@ Variables (i=0) → Loop (While i<10) → Agent (Process) → Variables (i++)
|
|||||||
</ul>
|
</ul>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab>
|
<Tab>
|
||||||
|
Available **inside** the loop only:
|
||||||
<ul className="list-disc space-y-2 pl-6">
|
<ul className="list-disc space-y-2 pl-6">
|
||||||
<li>
|
<li>
|
||||||
<strong>loop.currentItem</strong>: Current item being processed
|
<strong>{"<loop.index>"}</strong>: Current iteration number (0-based)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>loop.index</strong>: Current iteration number (0-based)
|
<strong>{"<loop.currentItem>"}</strong>: Current item being processed (forEach only)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>loop.items</strong>: Full collection (forEach loops)
|
<strong>{"<loop.items>"}</strong>: Full collection (forEach only)
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab>
|
<Tab>
|
||||||
<ul className="list-disc space-y-2 pl-6">
|
<ul className="list-disc space-y-2 pl-6">
|
||||||
<li>
|
<li>
|
||||||
<strong>loop.results</strong>: Array of all iteration results
|
<strong>{"<blockname.results>"}</strong>: Array of all iteration results (accessed via block name)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Structure</strong>: Results maintain iteration order
|
<strong>Structure</strong>: Results maintain iteration order
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Access</strong>: Available in blocks after the loop
|
<strong>Access</strong>: Available in blocks after the loop completes
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|||||||
@@ -76,11 +76,44 @@ Choose between two types of parallel execution:
|
|||||||
3. Drag a single block inside the parallel container
|
3. Drag a single block inside the parallel container
|
||||||
4. Connect the block as needed
|
4. Connect the block as needed
|
||||||
|
|
||||||
### Accessing Results
|
### Referencing Parallel Data
|
||||||
|
|
||||||
After a parallel block completes, you can access aggregated results:
|
There's an important distinction between referencing parallel data from **inside** vs **outside** the parallel block:
|
||||||
|
|
||||||
- **`<parallel.results>`**: Array of results from all parallel instances
|
<Tabs items={['Inside the Parallel', 'Outside the Parallel']}>
|
||||||
|
<Tab>
|
||||||
|
**Inside the parallel**, use `<parallel.>` references to access the current instance context:
|
||||||
|
|
||||||
|
- **`<parallel.index>`**: Current instance number (0-based)
|
||||||
|
- **`<parallel.currentItem>`**: Item for this instance (collection-based only)
|
||||||
|
- **`<parallel.items>`**: Full collection being distributed (collection-based only)
|
||||||
|
|
||||||
|
```
|
||||||
|
// Inside a Function block within the parallel
|
||||||
|
const idx = <parallel.index>; // 0, 1, 2, ...
|
||||||
|
const item = <parallel.currentItem>; // This instance's item
|
||||||
|
```
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
These references are only available for blocks **inside** the parallel container. They give you access to the current instance's context.
|
||||||
|
</Callout>
|
||||||
|
</Tab>
|
||||||
|
<Tab>
|
||||||
|
**Outside the parallel** (after it completes), reference the parallel block by its name to access aggregated results:
|
||||||
|
|
||||||
|
- **`<ParallelBlockName.results>`**: Array of results from all instances
|
||||||
|
|
||||||
|
```
|
||||||
|
// If your parallel block is named "Process Tasks"
|
||||||
|
const allResults = <processtasks.results>;
|
||||||
|
// Returns: [result1, result2, result3, ...]
|
||||||
|
```
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
After the parallel completes, use the parallel's block name (not `parallel.`) to access the collected results. The block name is normalized (lowercase, no spaces).
|
||||||
|
</Callout>
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
## Example Use Cases
|
## Example Use Cases
|
||||||
|
|
||||||
@@ -98,11 +131,11 @@ Parallel (["gpt-4o", "claude-3.7-sonnet", "gemini-2.5-pro"]) → Agent → Evalu
|
|||||||
|
|
||||||
### Result Aggregation
|
### Result Aggregation
|
||||||
|
|
||||||
Results from all parallel instances are automatically collected:
|
Results from all parallel instances are automatically collected and accessible via the block name:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// In a Function block after the parallel
|
// In a Function block after a parallel named "Process Tasks"
|
||||||
const allResults = input.parallel.results;
|
const allResults = <processtasks.results>;
|
||||||
// Returns: [result1, result2, result3, ...]
|
// Returns: [result1, result2, result3, ...]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -158,25 +191,26 @@ Understanding when to use each:
|
|||||||
</ul>
|
</ul>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab>
|
<Tab>
|
||||||
|
Available **inside** the parallel only:
|
||||||
<ul className="list-disc space-y-2 pl-6">
|
<ul className="list-disc space-y-2 pl-6">
|
||||||
<li>
|
<li>
|
||||||
<strong>parallel.currentItem</strong>: Item for this instance
|
<strong>{"<parallel.index>"}</strong>: Instance number (0-based)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>parallel.index</strong>: Instance number (0-based)
|
<strong>{"<parallel.currentItem>"}</strong>: Item for this instance (collection-based only)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>parallel.items</strong>: Full collection (collection-based)
|
<strong>{"<parallel.items>"}</strong>: Full collection (collection-based only)
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab>
|
<Tab>
|
||||||
<ul className="list-disc space-y-2 pl-6">
|
<ul className="list-disc space-y-2 pl-6">
|
||||||
<li>
|
<li>
|
||||||
<strong>parallel.results</strong>: Array of all instance results
|
<strong>{"<blockname.results>"}</strong>: Array of all instance results (accessed via block name)
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Access</strong>: Available in blocks after the parallel
|
<strong>Access</strong>: Available in blocks after the parallel completes
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|||||||
@@ -85,10 +85,10 @@ vi.mock('@/lib/execution/isolated-vm', () => ({
|
|||||||
vi.mock('@sim/logger', () => loggerMock)
|
vi.mock('@sim/logger', () => loggerMock)
|
||||||
|
|
||||||
vi.mock('@/lib/auth/hybrid', () => ({
|
vi.mock('@/lib/auth/hybrid', () => ({
|
||||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
checkInternalAuth: vi.fn().mockResolvedValue({
|
||||||
success: true,
|
success: true,
|
||||||
userId: 'user-123',
|
userId: 'user-123',
|
||||||
authType: 'session',
|
authType: 'internal_jwt',
|
||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -119,8 +119,8 @@ describe('Function Execute API Route', () => {
|
|||||||
|
|
||||||
describe('Security Tests', () => {
|
describe('Security Tests', () => {
|
||||||
it('should reject unauthorized requests', async () => {
|
it('should reject unauthorized requests', async () => {
|
||||||
const { checkHybridAuth } = await import('@/lib/auth/hybrid')
|
const { checkInternalAuth } = await import('@/lib/auth/hybrid')
|
||||||
vi.mocked(checkHybridAuth).mockResolvedValueOnce({
|
vi.mocked(checkInternalAuth).mockResolvedValueOnce({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Unauthorized',
|
error: 'Unauthorized',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { isE2bEnabled } from '@/lib/core/config/feature-flags'
|
import { isE2bEnabled } from '@/lib/core/config/feature-flags'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { executeInE2B } from '@/lib/execution/e2b'
|
import { executeInE2B } from '@/lib/execution/e2b'
|
||||||
@@ -582,7 +582,7 @@ export async function POST(req: NextRequest) {
|
|||||||
let resolvedCode = '' // Store resolved code for error reporting
|
let resolvedCode = '' // Store resolved code for error reporting
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(req)
|
const auth = await checkInternalAuth(req)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized function execution attempt`)
|
logger.warn(`[${requestId}] Unauthorized function execution attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { account } from '@sim/db/schema'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { eq } from 'drizzle-orm'
|
import { eq } from 'drizzle-orm'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils'
|
import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils'
|
||||||
import { refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
import { refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils'
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const startTime = Date.now()
|
const startTime = Date.now()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request, { requireWorkflowId: false })
|
const auth = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ describe('Custom Tools API Routes', () => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||||
success: true,
|
success: true,
|
||||||
userId: 'user-123',
|
userId: 'user-123',
|
||||||
authType: 'session',
|
authType: 'session',
|
||||||
@@ -254,7 +254,7 @@ describe('Custom Tools API Routes', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Unauthorized',
|
error: 'Unauthorized',
|
||||||
}),
|
}),
|
||||||
@@ -304,7 +304,7 @@ describe('Custom Tools API Routes', () => {
|
|||||||
describe('POST /api/tools/custom', () => {
|
describe('POST /api/tools/custom', () => {
|
||||||
it('should reject unauthorized requests', async () => {
|
it('should reject unauthorized requests', async () => {
|
||||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Unauthorized',
|
error: 'Unauthorized',
|
||||||
}),
|
}),
|
||||||
@@ -390,7 +390,7 @@ describe('Custom Tools API Routes', () => {
|
|||||||
|
|
||||||
it('should prevent unauthorized deletion of user-scoped tool', async () => {
|
it('should prevent unauthorized deletion of user-scoped tool', async () => {
|
||||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||||
success: true,
|
success: true,
|
||||||
userId: 'user-456',
|
userId: 'user-456',
|
||||||
authType: 'session',
|
authType: 'session',
|
||||||
@@ -413,7 +413,7 @@ describe('Custom Tools API Routes', () => {
|
|||||||
|
|
||||||
it('should reject unauthorized requests', async () => {
|
it('should reject unauthorized requests', async () => {
|
||||||
vi.doMock('@/lib/auth/hybrid', () => ({
|
vi.doMock('@/lib/auth/hybrid', () => ({
|
||||||
checkHybridAuth: vi.fn().mockResolvedValue({
|
checkSessionOrInternalAuth: vi.fn().mockResolvedValue({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Unauthorized',
|
error: 'Unauthorized',
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { and, desc, eq, isNull, or } from 'drizzle-orm'
|
import { and, desc, eq, isNull, or } from 'drizzle-orm'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkSessionOrInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { upsertCustomTools } from '@/lib/workflows/custom-tools/operations'
|
import { upsertCustomTools } from '@/lib/workflows/custom-tools/operations'
|
||||||
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
|
import { getUserEntityPermissions } from '@/lib/workspaces/permissions/utils'
|
||||||
@@ -42,8 +42,8 @@ export async function GET(request: NextRequest) {
|
|||||||
const workflowId = searchParams.get('workflowId')
|
const workflowId = searchParams.get('workflowId')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use hybrid auth to support session, API key, and internal JWT
|
// Use session/internal auth to support session and internal JWT (no API key access)
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkSessionOrInternalAuth(request, { requireWorkflowId: false })
|
||||||
if (!authResult.success || !authResult.userId) {
|
if (!authResult.success || !authResult.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized custom tools access attempt`)
|
logger.warn(`[${requestId}] Unauthorized custom tools access attempt`)
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
@@ -69,8 +69,8 @@ export async function GET(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check workspace permissions
|
// Check workspace permissions
|
||||||
// For internal JWT with workflowId: checkHybridAuth already resolved userId from workflow owner
|
// For internal JWT with workflowId: checkSessionOrInternalAuth already resolved userId from workflow owner
|
||||||
// For session/API key: verify user has access to the workspace
|
// For session: verify user has access to the workspace
|
||||||
// For legacy (no workspaceId): skip workspace check, rely on userId match
|
// For legacy (no workspaceId): skip workspace check, rely on userId match
|
||||||
if (resolvedWorkspaceId && !(authResult.authType === 'internal_jwt' && workflowId)) {
|
if (resolvedWorkspaceId && !(authResult.authType === 'internal_jwt' && workflowId)) {
|
||||||
const userPermission = await getUserEntityPermissions(
|
const userPermission = await getUserEntityPermissions(
|
||||||
@@ -116,8 +116,8 @@ export async function POST(req: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use hybrid auth (though this endpoint is only called from UI)
|
// Use session/internal auth (no API key access)
|
||||||
const authResult = await checkHybridAuth(req, { requireWorkflowId: false })
|
const authResult = await checkSessionOrInternalAuth(req, { requireWorkflowId: false })
|
||||||
if (!authResult.success || !authResult.userId) {
|
if (!authResult.success || !authResult.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized custom tools update attempt`)
|
logger.warn(`[${requestId}] Unauthorized custom tools update attempt`)
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
@@ -193,8 +193,8 @@ export async function DELETE(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Use hybrid auth (though this endpoint is only called from UI)
|
// Use session/internal auth (no API key access)
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkSessionOrInternalAuth(request, { requireWorkflowId: false })
|
||||||
if (!authResult.success || !authResult.userId) {
|
if (!authResult.success || !authResult.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized custom tool deletion attempt`)
|
logger.warn(`[${requestId}] Unauthorized custom tool deletion attempt`)
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { validateNumericId } from '@/lib/core/security/input-validation'
|
import { validateNumericId } from '@/lib/core/security/input-validation'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Discord send attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Discord send attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
|
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail add label attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail add label attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail archive attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail archive attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail delete attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail delete attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail draft attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail draft attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail mark read attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail mark read attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail mark unread attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail mark unread attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail move attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail move attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
|
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail remove label attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail remove label attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail send attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail send attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Gmail unarchive attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Gmail unarchive attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -56,7 +56,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Google Drive upload attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Google Drive upload attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { validateImageUrl } from '@/lib/core/security/input-validation'
|
import { validateImageUrl } from '@/lib/core/security/input-validation'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ export async function GET(request: NextRequest) {
|
|||||||
const imageUrl = url.searchParams.get('url')
|
const imageUrl = url.searchParams.get('url')
|
||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.error(`[${requestId}] Authentication failed for image proxy:`, authResult.error)
|
logger.error(`[${requestId}] Authentication failed for image proxy:`, authResult.error)
|
||||||
return new NextResponse('Unauthorized', { status: 401 })
|
return new NextResponse('Unauthorized', { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { Resend } from 'resend'
|
import { Resend } from 'resend'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized mail send attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized mail send attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Teams chat delete attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Teams chat delete attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Teams channel write attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Teams channel write attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Teams chat write attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Teams chat write attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||||
import { StorageService } from '@/lib/uploads'
|
import { StorageService } from '@/lib/uploads'
|
||||||
@@ -30,7 +30,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success || !authResult.userId) {
|
if (!authResult.success || !authResult.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Mistral parse attempt`, {
|
logger.warn(`[${requestId}] Unauthorized Mistral parse attempt`, {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { buildDeleteQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
import { buildDeleteQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
||||||
|
|
||||||
const logger = createLogger('MySQLDeleteAPI')
|
const logger = createLogger('MySQLDeleteAPI')
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized MySQL delete attempt`)
|
logger.warn(`[${requestId}] Unauthorized MySQL delete attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils'
|
import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils'
|
||||||
|
|
||||||
const logger = createLogger('MySQLExecuteAPI')
|
const logger = createLogger('MySQLExecuteAPI')
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized MySQL execute attempt`)
|
logger.warn(`[${requestId}] Unauthorized MySQL execute attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { buildInsertQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
import { buildInsertQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
||||||
|
|
||||||
const logger = createLogger('MySQLInsertAPI')
|
const logger = createLogger('MySQLInsertAPI')
|
||||||
@@ -43,7 +43,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized MySQL insert attempt`)
|
logger.warn(`[${requestId}] Unauthorized MySQL insert attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createMySQLConnection, executeIntrospect } from '@/app/api/tools/mysql/utils'
|
import { createMySQLConnection, executeIntrospect } from '@/app/api/tools/mysql/utils'
|
||||||
|
|
||||||
const logger = createLogger('MySQLIntrospectAPI')
|
const logger = createLogger('MySQLIntrospectAPI')
|
||||||
@@ -20,7 +20,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized MySQL introspect attempt`)
|
logger.warn(`[${requestId}] Unauthorized MySQL introspect attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils'
|
import { createMySQLConnection, executeQuery, validateQuery } from '@/app/api/tools/mysql/utils'
|
||||||
|
|
||||||
const logger = createLogger('MySQLQueryAPI')
|
const logger = createLogger('MySQLQueryAPI')
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized MySQL query attempt`)
|
logger.warn(`[${requestId}] Unauthorized MySQL query attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { buildUpdateQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
import { buildUpdateQuery, createMySQLConnection, executeQuery } from '@/app/api/tools/mysql/utils'
|
||||||
|
|
||||||
const logger = createLogger('MySQLUpdateAPI')
|
const logger = createLogger('MySQLUpdateAPI')
|
||||||
@@ -41,7 +41,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized MySQL update attempt`)
|
logger.warn(`[${requestId}] Unauthorized MySQL update attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import * as XLSX from 'xlsx'
|
import * as XLSX from 'xlsx'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation'
|
import { validateMicrosoftGraphId } from '@/lib/core/security/input-validation'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import {
|
import {
|
||||||
@@ -39,7 +39,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized OneDrive upload attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized OneDrive upload attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Outlook copy attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Outlook copy attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Outlook delete attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Outlook delete attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Outlook draft attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Outlook draft attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Outlook mark read attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Outlook mark read attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -17,7 +17,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Outlook mark unread attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Outlook mark unread attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -18,7 +18,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Outlook move attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Outlook move attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Outlook send attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Outlook send attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createPostgresConnection, executeDelete } from '@/app/api/tools/postgresql/utils'
|
import { createPostgresConnection, executeDelete } from '@/app/api/tools/postgresql/utils'
|
||||||
|
|
||||||
const logger = createLogger('PostgreSQLDeleteAPI')
|
const logger = createLogger('PostgreSQLDeleteAPI')
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL delete attempt`)
|
logger.warn(`[${requestId}] Unauthorized PostgreSQL delete attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import {
|
import {
|
||||||
createPostgresConnection,
|
createPostgresConnection,
|
||||||
executeQuery,
|
executeQuery,
|
||||||
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL execute attempt`)
|
logger.warn(`[${requestId}] Unauthorized PostgreSQL execute attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createPostgresConnection, executeInsert } from '@/app/api/tools/postgresql/utils'
|
import { createPostgresConnection, executeInsert } from '@/app/api/tools/postgresql/utils'
|
||||||
|
|
||||||
const logger = createLogger('PostgreSQLInsertAPI')
|
const logger = createLogger('PostgreSQLInsertAPI')
|
||||||
@@ -43,7 +43,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL insert attempt`)
|
logger.warn(`[${requestId}] Unauthorized PostgreSQL insert attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createPostgresConnection, executeIntrospect } from '@/app/api/tools/postgresql/utils'
|
import { createPostgresConnection, executeIntrospect } from '@/app/api/tools/postgresql/utils'
|
||||||
|
|
||||||
const logger = createLogger('PostgreSQLIntrospectAPI')
|
const logger = createLogger('PostgreSQLIntrospectAPI')
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL introspect attempt`)
|
logger.warn(`[${requestId}] Unauthorized PostgreSQL introspect attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createPostgresConnection, executeQuery } from '@/app/api/tools/postgresql/utils'
|
import { createPostgresConnection, executeQuery } from '@/app/api/tools/postgresql/utils'
|
||||||
|
|
||||||
const logger = createLogger('PostgreSQLQueryAPI')
|
const logger = createLogger('PostgreSQLQueryAPI')
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL query attempt`)
|
logger.warn(`[${requestId}] Unauthorized PostgreSQL query attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createPostgresConnection, executeUpdate } from '@/app/api/tools/postgresql/utils'
|
import { createPostgresConnection, executeUpdate } from '@/app/api/tools/postgresql/utils'
|
||||||
|
|
||||||
const logger = createLogger('PostgreSQLUpdateAPI')
|
const logger = createLogger('PostgreSQLUpdateAPI')
|
||||||
@@ -41,7 +41,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized PostgreSQL update attempt`)
|
logger.warn(`[${requestId}] Unauthorized PostgreSQL update attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||||
import { StorageService } from '@/lib/uploads'
|
import { StorageService } from '@/lib/uploads'
|
||||||
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success || !authResult.userId) {
|
if (!authResult.success || !authResult.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Pulse parse attempt`, {
|
logger.warn(`[${requestId}] Unauthorized Pulse parse attempt`, {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||||
import { StorageService } from '@/lib/uploads'
|
import { StorageService } from '@/lib/uploads'
|
||||||
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success || !authResult.userId) {
|
if (!authResult.success || !authResult.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Reducto parse attempt`, {
|
logger.warn(`[${requestId}] Unauthorized Reducto parse attempt`, {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { CopyObjectCommand, type ObjectCannedACL, S3Client } from '@aws-sdk/clie
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -24,7 +24,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized S3 copy object attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized S3 copy object attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized S3 delete object attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized S3 delete object attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ListObjectsV2Command, S3Client } from '@aws-sdk/client-s3'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized S3 list objects attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized S3 list objects attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { type ObjectCannedACL, PutObjectCommand, S3Client } from '@aws-sdk/clien
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -27,7 +27,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized S3 put object attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized S3 put object attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { SEARCH_TOOL_COST } from '@/lib/billing/constants'
|
import { SEARCH_TOOL_COST } from '@/lib/billing/constants'
|
||||||
import { env } from '@/lib/core/config/env'
|
import { env } from '@/lib/core/config/env'
|
||||||
import { executeTool } from '@/tools'
|
import { executeTool } from '@/tools'
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const { searchParams: urlParams } = new URL(request.url)
|
const { searchParams: urlParams } = new URL(request.url)
|
||||||
const workflowId = urlParams.get('workflowId') || undefined
|
const workflowId = urlParams.get('workflowId') || undefined
|
||||||
|
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success || !authResult.userId) {
|
if (!authResult.success || !authResult.userId) {
|
||||||
const errorMessage = workflowId ? 'Workflow not found' : authResult.error || 'Unauthorized'
|
const errorMessage = workflowId ? 'Workflow not found' : authResult.error || 'Unauthorized'
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import type { SFTPWrapper } from 'ssh2'
|
import type { SFTPWrapper } from 'ssh2'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import {
|
import {
|
||||||
createSftpConnection,
|
createSftpConnection,
|
||||||
@@ -72,7 +72,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SFTP delete attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized SFTP delete attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import path from 'path'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { createSftpConnection, getSftp, isPathSafe, sanitizePath } from '@/app/api/tools/sftp/utils'
|
import { createSftpConnection, getSftp, isPathSafe, sanitizePath } from '@/app/api/tools/sftp/utils'
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SFTP download attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized SFTP download attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import {
|
import {
|
||||||
createSftpConnection,
|
createSftpConnection,
|
||||||
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SFTP list attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized SFTP list attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import type { SFTPWrapper } from 'ssh2'
|
import type { SFTPWrapper } from 'ssh2'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import {
|
import {
|
||||||
createSftpConnection,
|
createSftpConnection,
|
||||||
@@ -60,7 +60,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SFTP mkdir attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized SFTP mkdir attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -44,7 +44,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SFTP upload attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized SFTP upload attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SharePoint upload attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized SharePoint upload attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ const SlackAddReactionSchema = z.object({
|
|||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ const SlackDeleteMessageSchema = z.object({
|
|||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { openDMChannel } from '../utils'
|
import { openDMChannel } from '../utils'
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Slack read messages attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Slack read messages attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { sendSlackMessage } from '../utils'
|
import { sendSlackMessage } from '../utils'
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Slack send attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Slack send attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
|
|
||||||
export const dynamic = 'force-dynamic'
|
export const dynamic = 'force-dynamic'
|
||||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Slack update message attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Slack update message attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { env } from '@/lib/core/config/env'
|
import { env } from '@/lib/core/config/env'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { type SMSOptions, sendSMS } from '@/lib/messaging/sms/service'
|
import { type SMSOptions, sendSMS } from '@/lib/messaging/sms/service'
|
||||||
@@ -19,7 +19,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SMS send attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized SMS send attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import nodemailer from 'nodemailer'
|
import nodemailer from 'nodemailer'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SMTP send attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized SMTP send attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils'
|
import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils'
|
||||||
|
|
||||||
const logger = createLogger('SSHCheckCommandExistsAPI')
|
const logger = createLogger('SSHCheckCommandExistsAPI')
|
||||||
@@ -21,7 +21,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH check command exists attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH check command exists attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import type { Client, SFTPWrapper, Stats } from 'ssh2'
|
import type { Client, SFTPWrapper, Stats } from 'ssh2'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import {
|
import {
|
||||||
createSSHConnection,
|
createSSHConnection,
|
||||||
getFileType,
|
getFileType,
|
||||||
@@ -40,7 +40,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH check file exists attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH check file exists attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import {
|
import {
|
||||||
createSSHConnection,
|
createSSHConnection,
|
||||||
escapeShellArg,
|
escapeShellArg,
|
||||||
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH create directory attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH create directory attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import {
|
import {
|
||||||
createSSHConnection,
|
createSSHConnection,
|
||||||
escapeShellArg,
|
escapeShellArg,
|
||||||
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH delete file attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH delete file attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import type { Client, SFTPWrapper } from 'ssh2'
|
import type { Client, SFTPWrapper } from 'ssh2'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
|
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
|
||||||
|
|
||||||
const logger = createLogger('SSHDownloadFileAPI')
|
const logger = createLogger('SSHDownloadFileAPI')
|
||||||
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH download file attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH download file attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createSSHConnection, executeSSHCommand, sanitizeCommand } from '@/app/api/tools/ssh/utils'
|
import { createSSHConnection, executeSSHCommand, sanitizeCommand } from '@/app/api/tools/ssh/utils'
|
||||||
|
|
||||||
const logger = createLogger('SSHExecuteCommandAPI')
|
const logger = createLogger('SSHExecuteCommandAPI')
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH execute command attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH execute command attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils'
|
import { createSSHConnection, escapeShellArg, executeSSHCommand } from '@/app/api/tools/ssh/utils'
|
||||||
|
|
||||||
const logger = createLogger('SSHExecuteScriptAPI')
|
const logger = createLogger('SSHExecuteScriptAPI')
|
||||||
@@ -23,7 +23,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH execute script attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH execute script attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createSSHConnection, executeSSHCommand } from '@/app/api/tools/ssh/utils'
|
import { createSSHConnection, executeSSHCommand } from '@/app/api/tools/ssh/utils'
|
||||||
|
|
||||||
const logger = createLogger('SSHGetSystemInfoAPI')
|
const logger = createLogger('SSHGetSystemInfoAPI')
|
||||||
@@ -20,7 +20,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH get system info attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH get system info attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import type { Client, FileEntry, SFTPWrapper } from 'ssh2'
|
import type { Client, FileEntry, SFTPWrapper } from 'ssh2'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import {
|
import {
|
||||||
createSSHConnection,
|
createSSHConnection,
|
||||||
getFileType,
|
getFileType,
|
||||||
@@ -61,7 +61,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH list directory attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH list directory attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import {
|
import {
|
||||||
createSSHConnection,
|
createSSHConnection,
|
||||||
escapeShellArg,
|
escapeShellArg,
|
||||||
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH move/rename attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH move/rename attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import type { Client, SFTPWrapper } from 'ssh2'
|
import type { Client, SFTPWrapper } from 'ssh2'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
|
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
|
||||||
|
|
||||||
const logger = createLogger('SSHReadFileContentAPI')
|
const logger = createLogger('SSHReadFileContentAPI')
|
||||||
@@ -36,7 +36,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH read file content attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH read file content attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import type { Client, SFTPWrapper } from 'ssh2'
|
import type { Client, SFTPWrapper } from 'ssh2'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
|
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
|
||||||
|
|
||||||
const logger = createLogger('SSHUploadFileAPI')
|
const logger = createLogger('SSHUploadFileAPI')
|
||||||
@@ -38,7 +38,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH upload file attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH upload file attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createLogger } from '@sim/logger'
|
|||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import type { Client, SFTPWrapper } from 'ssh2'
|
import type { Client, SFTPWrapper } from 'ssh2'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
|
import { createSSHConnection, sanitizePath } from '@/app/api/tools/ssh/utils'
|
||||||
|
|
||||||
const logger = createLogger('SSHWriteFileContentAPI')
|
const logger = createLogger('SSHWriteFileContentAPI')
|
||||||
@@ -37,7 +37,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = randomUUID().slice(0, 8)
|
const requestId = randomUUID().slice(0, 8)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auth = await checkHybridAuth(request)
|
const auth = await checkInternalAuth(request)
|
||||||
if (!auth.success || !auth.userId) {
|
if (!auth.success || !auth.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized SSH write file content attempt`)
|
logger.warn(`[${requestId}] Unauthorized SSH write file content attempt`)
|
||||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { extractAudioFromVideo, isVideoFile } from '@/lib/audio/extractor'
|
import { extractAudioFromVideo, isVideoFile } from '@/lib/audio/extractor'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
import type { UserFile } from '@/executor/types'
|
import type { UserFile } from '@/executor/types'
|
||||||
import type { TranscriptSegment } from '@/tools/stt/types'
|
import type { TranscriptSegment } from '@/tools/stt/types'
|
||||||
@@ -40,7 +40,7 @@ export async function POST(request: NextRequest) {
|
|||||||
logger.info(`[${requestId}] STT transcription request started`)
|
logger.info(`[${requestId}] STT transcription request started`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, {
|
const authResult = await checkInternalAuth(request, {
|
||||||
requireWorkflowId: false,
|
requireWorkflowId: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import crypto from 'crypto'
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import {
|
import {
|
||||||
validateAwsRegion,
|
validateAwsRegion,
|
||||||
validateExternalUrl,
|
validateExternalUrl,
|
||||||
@@ -292,7 +292,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success || !authResult.userId) {
|
if (!authResult.success || !authResult.userId) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Textract parse attempt`, {
|
logger.warn(`[${requestId}] Unauthorized Textract parse attempt`, {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import type { NextRequest } from 'next/server'
|
import type { NextRequest } from 'next/server'
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
|
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
|
||||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||||
import { StorageService } from '@/lib/uploads'
|
import { StorageService } from '@/lib/uploads'
|
||||||
@@ -10,7 +10,7 @@ const logger = createLogger('ProxyTTSAPI')
|
|||||||
|
|
||||||
export async function POST(request: NextRequest) {
|
export async function POST(request: NextRequest) {
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.error('Authentication failed for TTS proxy:', authResult.error)
|
logger.error('Authentication failed for TTS proxy:', authResult.error)
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import type { NextRequest } from 'next/server'
|
import type { NextRequest } from 'next/server'
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
|
import { validateAlphanumericId } from '@/lib/core/security/input-validation'
|
||||||
import { getBaseUrl } from '@/lib/core/utils/urls'
|
import { getBaseUrl } from '@/lib/core/utils/urls'
|
||||||
import { StorageService } from '@/lib/uploads'
|
import { StorageService } from '@/lib/uploads'
|
||||||
@@ -87,7 +87,7 @@ export async function POST(request: NextRequest) {
|
|||||||
logger.info(`[${requestId}] TTS unified request started`)
|
logger.info(`[${requestId}] TTS unified request started`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.error('Authentication failed for TTS unified proxy:', authResult.error)
|
logger.error('Authentication failed for TTS unified proxy:', authResult.error)
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
import type { UserFile } from '@/executor/types'
|
import type { UserFile } from '@/executor/types'
|
||||||
import type { VideoRequestBody } from '@/tools/video/types'
|
import type { VideoRequestBody } from '@/tools/video/types'
|
||||||
@@ -15,7 +15,7 @@ export async function POST(request: NextRequest) {
|
|||||||
logger.info(`[${requestId}] Video generation request started`)
|
logger.info(`[${requestId}] Video generation request started`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
import { processSingleFileToUserFile } from '@/lib/uploads/utils/file-utils'
|
||||||
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
|
||||||
@@ -22,7 +22,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized Vision analyze attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized Vision analyze attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { type NextRequest, NextResponse } from 'next/server'
|
import { type NextRequest, NextResponse } from 'next/server'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { checkHybridAuth } from '@/lib/auth/hybrid'
|
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||||
import { generateRequestId } from '@/lib/core/utils/request'
|
import { generateRequestId } from '@/lib/core/utils/request'
|
||||||
import {
|
import {
|
||||||
getFileExtension,
|
getFileExtension,
|
||||||
@@ -31,7 +31,7 @@ export async function POST(request: NextRequest) {
|
|||||||
const requestId = generateRequestId()
|
const requestId = generateRequestId()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authResult = await checkHybridAuth(request, { requireWorkflowId: false })
|
const authResult = await checkInternalAuth(request, { requireWorkflowId: false })
|
||||||
|
|
||||||
if (!authResult.success) {
|
if (!authResult.success) {
|
||||||
logger.warn(`[${requestId}] Unauthorized WordPress upload attempt: ${authResult.error}`)
|
logger.warn(`[${requestId}] Unauthorized WordPress upload attempt: ${authResult.error}`)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { normalizeName } from '@/executor/constants'
|
|||||||
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
||||||
import type { ExecutionMetadata, IterationContext } from '@/executor/execution/types'
|
import type { ExecutionMetadata, IterationContext } from '@/executor/execution/types'
|
||||||
import type { NormalizedBlockOutput, StreamingExecution } from '@/executor/types'
|
import type { NormalizedBlockOutput, StreamingExecution } from '@/executor/types'
|
||||||
|
import { hasExecutionResult } from '@/executor/utils/errors'
|
||||||
import { Serializer } from '@/serializer'
|
import { Serializer } from '@/serializer'
|
||||||
import { CORE_TRIGGER_TYPES, type CoreTriggerType } from '@/stores/logs/filters/types'
|
import { CORE_TRIGGER_TYPES, type CoreTriggerType } from '@/stores/logs/filters/types'
|
||||||
|
|
||||||
@@ -467,17 +468,17 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
|||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.json(filteredResult)
|
return NextResponse.json(filteredResult)
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = error.message || 'Unknown error'
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
||||||
logger.error(`[${requestId}] Non-SSE execution failed: ${errorMessage}`)
|
logger.error(`[${requestId}] Non-SSE execution failed: ${errorMessage}`)
|
||||||
|
|
||||||
const executionResult = error.executionResult
|
const executionResult = hasExecutionResult(error) ? error.executionResult : undefined
|
||||||
|
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
output: executionResult?.output,
|
output: executionResult?.output,
|
||||||
error: executionResult?.error || error.message || 'Execution failed',
|
error: executionResult?.error || errorMessage || 'Execution failed',
|
||||||
metadata: executionResult?.metadata
|
metadata: executionResult?.metadata
|
||||||
? {
|
? {
|
||||||
duration: executionResult.metadata.duration,
|
duration: executionResult.metadata.duration,
|
||||||
@@ -788,11 +789,11 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
|
|||||||
|
|
||||||
// Cleanup base64 cache for this execution
|
// Cleanup base64 cache for this execution
|
||||||
await cleanupExecutionBase64Cache(executionId)
|
await cleanupExecutionBase64Cache(executionId)
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
const errorMessage = error.message || 'Unknown error'
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error'
|
||||||
logger.error(`[${requestId}] SSE execution failed: ${errorMessage}`)
|
logger.error(`[${requestId}] SSE execution failed: ${errorMessage}`)
|
||||||
|
|
||||||
const executionResult = error.executionResult
|
const executionResult = hasExecutionResult(error) ? error.executionResult : undefined
|
||||||
|
|
||||||
sendEvent({
|
sendEvent({
|
||||||
type: 'execution:error',
|
type: 'execution:error',
|
||||||
|
|||||||
@@ -1260,7 +1260,6 @@ async function handleRun(
|
|||||||
const instance = getClientTool(toolCall.id)
|
const instance = getClientTool(toolCall.id)
|
||||||
|
|
||||||
if (!instance && isIntegrationTool(toolCall.name)) {
|
if (!instance && isIntegrationTool(toolCall.name)) {
|
||||||
setToolCallState(toolCall, 'executing')
|
|
||||||
onStateChange?.('executing')
|
onStateChange?.('executing')
|
||||||
try {
|
try {
|
||||||
await useCopilotStore.getState().executeIntegrationTool(toolCall.id)
|
await useCopilotStore.getState().executeIntegrationTool(toolCall.id)
|
||||||
|
|||||||
@@ -496,7 +496,7 @@ export function DeployModal({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{apiDeployWarnings.length > 0 && (
|
{apiDeployWarnings.length > 0 && (
|
||||||
<div className='mb-3 rounded-[4px] border border-amber-500/30 bg-amber-500/10 p-3 text-amber-700 dark:text-amber-400 text-sm'>
|
<div className='mb-3 rounded-[4px] border border-amber-500/30 bg-amber-500/10 p-3 text-amber-700 text-sm dark:text-amber-400'>
|
||||||
<div className='font-semibold'>Deployment Warning</div>
|
<div className='font-semibold'>Deployment Warning</div>
|
||||||
{apiDeployWarnings.map((warning, index) => (
|
{apiDeployWarnings.map((warning, index) => (
|
||||||
<div key={index}>{warning}</div>
|
<div key={index}>{warning}</div>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
} from '@/lib/workflows/triggers/triggers'
|
} from '@/lib/workflows/triggers/triggers'
|
||||||
import { useCurrentWorkflow } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-current-workflow'
|
import { useCurrentWorkflow } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-current-workflow'
|
||||||
import type { BlockLog, ExecutionResult, StreamingExecution } from '@/executor/types'
|
import type { BlockLog, ExecutionResult, StreamingExecution } from '@/executor/types'
|
||||||
|
import { hasExecutionResult } from '@/executor/utils/errors'
|
||||||
import { coerceValue } from '@/executor/utils/start-block'
|
import { coerceValue } from '@/executor/utils/start-block'
|
||||||
import { subscriptionKeys } from '@/hooks/queries/subscription'
|
import { subscriptionKeys } from '@/hooks/queries/subscription'
|
||||||
import { useExecutionStream } from '@/hooks/use-execution-stream'
|
import { useExecutionStream } from '@/hooks/use-execution-stream'
|
||||||
@@ -76,17 +77,6 @@ function normalizeErrorMessage(error: unknown): string {
|
|||||||
return WORKFLOW_EXECUTION_FAILURE_MESSAGE
|
return WORKFLOW_EXECUTION_FAILURE_MESSAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
function isExecutionResult(value: unknown): value is ExecutionResult {
|
|
||||||
if (!isRecord(value)) return false
|
|
||||||
return typeof value.success === 'boolean' && isRecord(value.output)
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractExecutionResult(error: unknown): ExecutionResult | null {
|
|
||||||
if (!isRecord(error)) return null
|
|
||||||
const candidate = error.executionResult
|
|
||||||
return isExecutionResult(candidate) ? candidate : null
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useWorkflowExecution() {
|
export function useWorkflowExecution() {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const currentWorkflow = useCurrentWorkflow()
|
const currentWorkflow = useCurrentWorkflow()
|
||||||
@@ -1138,11 +1128,11 @@ export function useWorkflowExecution() {
|
|||||||
|
|
||||||
const handleExecutionError = (error: unknown, options?: { executionId?: string }) => {
|
const handleExecutionError = (error: unknown, options?: { executionId?: string }) => {
|
||||||
const normalizedMessage = normalizeErrorMessage(error)
|
const normalizedMessage = normalizeErrorMessage(error)
|
||||||
const executionResultFromError = extractExecutionResult(error)
|
|
||||||
|
|
||||||
let errorResult: ExecutionResult
|
let errorResult: ExecutionResult
|
||||||
|
|
||||||
if (executionResultFromError) {
|
if (hasExecutionResult(error)) {
|
||||||
|
const executionResultFromError = error.executionResult
|
||||||
const logs = Array.isArray(executionResultFromError.logs) ? executionResultFromError.logs : []
|
const logs = Array.isArray(executionResultFromError.logs) ? executionResultFromError.logs : []
|
||||||
|
|
||||||
errorResult = {
|
errorResult = {
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ import { useWorkflowDiffStore } from '@/stores/workflow-diff/store'
|
|||||||
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
|
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
|
||||||
import { getUniqueBlockName, prepareBlockState } from '@/stores/workflows/utils'
|
import { getUniqueBlockName, prepareBlockState } from '@/stores/workflows/utils'
|
||||||
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
|
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
|
||||||
|
import type { BlockState } from '@/stores/workflows/workflow/types'
|
||||||
|
|
||||||
/** Lazy-loaded components for non-critical UI that can load after initial render */
|
/** Lazy-loaded components for non-critical UI that can load after initial render */
|
||||||
const LazyChat = lazy(() =>
|
const LazyChat = lazy(() =>
|
||||||
@@ -535,8 +536,7 @@ const WorkflowContent = React.memo(() => {
|
|||||||
return edgesToFilter.filter((edge) => {
|
return edgesToFilter.filter((edge) => {
|
||||||
const sourceBlock = blocks[edge.source]
|
const sourceBlock = blocks[edge.source]
|
||||||
const targetBlock = blocks[edge.target]
|
const targetBlock = blocks[edge.target]
|
||||||
if (!sourceBlock || !targetBlock) return false
|
return Boolean(sourceBlock && targetBlock)
|
||||||
return !isAnnotationOnlyBlock(sourceBlock.type) && !isAnnotationOnlyBlock(targetBlock.type)
|
|
||||||
})
|
})
|
||||||
}, [edges, isShowingDiff, isDiffReady, diffAnalysis, blocks])
|
}, [edges, isShowingDiff, isDiffReady, diffAnalysis, blocks])
|
||||||
|
|
||||||
@@ -1097,6 +1097,13 @@ const WorkflowContent = React.memo(() => {
|
|||||||
[collaborativeBatchRemoveEdges]
|
[collaborativeBatchRemoveEdges]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const isAutoConnectSourceCandidate = useCallback((block: BlockState): boolean => {
|
||||||
|
if (!block.enabled) return false
|
||||||
|
if (block.type === 'response') return false
|
||||||
|
if (isAnnotationOnlyBlock(block.type)) return false
|
||||||
|
return true
|
||||||
|
}, [])
|
||||||
|
|
||||||
/** Finds the closest block to a position for auto-connect. */
|
/** Finds the closest block to a position for auto-connect. */
|
||||||
const findClosestOutput = useCallback(
|
const findClosestOutput = useCallback(
|
||||||
(newNodePosition: { x: number; y: number }): BlockData | null => {
|
(newNodePosition: { x: number; y: number }): BlockData | null => {
|
||||||
@@ -1109,8 +1116,7 @@ const WorkflowContent = React.memo(() => {
|
|||||||
position: { x: number; y: number }
|
position: { x: number; y: number }
|
||||||
distanceSquared: number
|
distanceSquared: number
|
||||||
} | null>((acc, [id, block]) => {
|
} | null>((acc, [id, block]) => {
|
||||||
if (!block.enabled) return acc
|
if (!isAutoConnectSourceCandidate(block)) return acc
|
||||||
if (block.type === 'response') return acc
|
|
||||||
const node = nodeIndex.get(id)
|
const node = nodeIndex.get(id)
|
||||||
if (!node) return acc
|
if (!node) return acc
|
||||||
|
|
||||||
@@ -1140,7 +1146,7 @@ const WorkflowContent = React.memo(() => {
|
|||||||
position: closest.position,
|
position: closest.position,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[blocks, getNodes, getNodeAnchorPosition, isPointInLoopNode]
|
[blocks, getNodes, getNodeAnchorPosition, isPointInLoopNode, isAutoConnectSourceCandidate]
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Determines the appropriate source handle based on block type. */
|
/** Determines the appropriate source handle based on block type. */
|
||||||
@@ -1208,7 +1214,8 @@ const WorkflowContent = React.memo(() => {
|
|||||||
position: { x: number; y: number }
|
position: { x: number; y: number }
|
||||||
distanceSquared: number
|
distanceSquared: number
|
||||||
} | null>((acc, block) => {
|
} | null>((acc, block) => {
|
||||||
if (block.type === 'response') return acc
|
const blockState = blocks[block.id]
|
||||||
|
if (!blockState || !isAutoConnectSourceCandidate(blockState)) return acc
|
||||||
const distanceSquared =
|
const distanceSquared =
|
||||||
(block.position.x - targetPosition.x) ** 2 + (block.position.y - targetPosition.y) ** 2
|
(block.position.x - targetPosition.x) ** 2 + (block.position.y - targetPosition.y) ** 2
|
||||||
if (!acc || distanceSquared < acc.distanceSquared) {
|
if (!acc || distanceSquared < acc.distanceSquared) {
|
||||||
@@ -1225,7 +1232,7 @@ const WorkflowContent = React.memo(() => {
|
|||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
},
|
},
|
||||||
[]
|
[blocks, isAutoConnectSourceCandidate]
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1241,8 +1248,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
position: { x: number; y: number },
|
position: { x: number; y: number },
|
||||||
targetBlockId: string,
|
targetBlockId: string,
|
||||||
options: {
|
options: {
|
||||||
blockType: string
|
|
||||||
enableTriggerMode?: boolean
|
|
||||||
targetParentId?: string | null
|
targetParentId?: string | null
|
||||||
existingChildBlocks?: { id: string; type: string; position: { x: number; y: number } }[]
|
existingChildBlocks?: { id: string; type: string; position: { x: number; y: number } }[]
|
||||||
containerId?: string
|
containerId?: string
|
||||||
@@ -1250,17 +1255,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
): Edge | undefined => {
|
): Edge | undefined => {
|
||||||
if (!autoConnectRef.current) return undefined
|
if (!autoConnectRef.current) return undefined
|
||||||
|
|
||||||
// Don't auto-connect starter or annotation-only blocks
|
|
||||||
if (options.blockType === 'starter' || isAnnotationOnlyBlock(options.blockType)) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if target is a trigger block
|
|
||||||
const targetBlockConfig = getBlock(options.blockType)
|
|
||||||
const isTargetTrigger =
|
|
||||||
options.enableTriggerMode || targetBlockConfig?.category === 'triggers'
|
|
||||||
if (isTargetTrigger) return undefined
|
|
||||||
|
|
||||||
// Case 1: Adding block inside a container with existing children
|
// Case 1: Adding block inside a container with existing children
|
||||||
if (options.existingChildBlocks && options.existingChildBlocks.length > 0) {
|
if (options.existingChildBlocks && options.existingChildBlocks.length > 0) {
|
||||||
const closestBlock = findClosestBlockInSet(options.existingChildBlocks, position)
|
const closestBlock = findClosestBlockInSet(options.existingChildBlocks, position)
|
||||||
@@ -1368,7 +1362,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
const name = getUniqueBlockName(baseName, blocks)
|
const name = getUniqueBlockName(baseName, blocks)
|
||||||
|
|
||||||
const autoConnectEdge = tryCreateAutoConnectEdge(position, id, {
|
const autoConnectEdge = tryCreateAutoConnectEdge(position, id, {
|
||||||
blockType: data.type,
|
|
||||||
targetParentId: null,
|
targetParentId: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1439,8 +1432,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
.map((b) => ({ id: b.id, type: b.type, position: b.position }))
|
.map((b) => ({ id: b.id, type: b.type, position: b.position }))
|
||||||
|
|
||||||
const autoConnectEdge = tryCreateAutoConnectEdge(relativePosition, id, {
|
const autoConnectEdge = tryCreateAutoConnectEdge(relativePosition, id, {
|
||||||
blockType: data.type,
|
|
||||||
enableTriggerMode: data.enableTriggerMode,
|
|
||||||
targetParentId: containerInfo.loopId,
|
targetParentId: containerInfo.loopId,
|
||||||
existingChildBlocks,
|
existingChildBlocks,
|
||||||
containerId: containerInfo.loopId,
|
containerId: containerInfo.loopId,
|
||||||
@@ -1469,8 +1460,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
if (checkTriggerConstraints(data.type)) return
|
if (checkTriggerConstraints(data.type)) return
|
||||||
|
|
||||||
const autoConnectEdge = tryCreateAutoConnectEdge(position, id, {
|
const autoConnectEdge = tryCreateAutoConnectEdge(position, id, {
|
||||||
blockType: data.type,
|
|
||||||
enableTriggerMode: data.enableTriggerMode,
|
|
||||||
targetParentId: null,
|
targetParentId: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1526,7 +1515,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
const name = getUniqueBlockName(baseName, blocks)
|
const name = getUniqueBlockName(baseName, blocks)
|
||||||
|
|
||||||
const autoConnectEdge = tryCreateAutoConnectEdge(basePosition, id, {
|
const autoConnectEdge = tryCreateAutoConnectEdge(basePosition, id, {
|
||||||
blockType: type,
|
|
||||||
targetParentId: null,
|
targetParentId: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1562,8 +1550,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
const name = getUniqueBlockName(baseName, blocks)
|
const name = getUniqueBlockName(baseName, blocks)
|
||||||
|
|
||||||
const autoConnectEdge = tryCreateAutoConnectEdge(basePosition, id, {
|
const autoConnectEdge = tryCreateAutoConnectEdge(basePosition, id, {
|
||||||
blockType: type,
|
|
||||||
enableTriggerMode,
|
|
||||||
targetParentId: null,
|
targetParentId: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -2364,24 +2350,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
|
|
||||||
if (!sourceNode || !targetNode) return
|
if (!sourceNode || !targetNode) return
|
||||||
|
|
||||||
// Prevent connections to/from annotation-only blocks (non-executable)
|
|
||||||
if (
|
|
||||||
isAnnotationOnlyBlock(sourceNode.data?.type) ||
|
|
||||||
isAnnotationOnlyBlock(targetNode.data?.type)
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent incoming connections to trigger blocks (webhook, schedule, etc.)
|
|
||||||
if (targetNode.data?.config?.category === 'triggers') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent incoming connections to starter blocks (still keep separate for backward compatibility)
|
|
||||||
if (targetNode.data?.type === 'starter') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get parent information (handle container start node case)
|
// Get parent information (handle container start node case)
|
||||||
const sourceParentId =
|
const sourceParentId =
|
||||||
blocks[sourceNode.id]?.data?.parentId ||
|
blocks[sourceNode.id]?.data?.parentId ||
|
||||||
@@ -2787,7 +2755,6 @@ const WorkflowContent = React.memo(() => {
|
|||||||
.map((b) => ({ id: b.id, type: b.type, position: b.position }))
|
.map((b) => ({ id: b.id, type: b.type, position: b.position }))
|
||||||
|
|
||||||
const autoConnectEdge = tryCreateAutoConnectEdge(relativePositionBefore, node.id, {
|
const autoConnectEdge = tryCreateAutoConnectEdge(relativePositionBefore, node.id, {
|
||||||
blockType: node.data?.type || '',
|
|
||||||
targetParentId: potentialParentId,
|
targetParentId: potentialParentId,
|
||||||
existingChildBlocks,
|
existingChildBlocks,
|
||||||
containerId: potentialParentId,
|
containerId: potentialParentId,
|
||||||
|
|||||||
@@ -3,11 +3,26 @@
|
|||||||
import { memo, useMemo } from 'react'
|
import { memo, useMemo } from 'react'
|
||||||
import { Handle, type NodeProps, Position } from 'reactflow'
|
import { Handle, type NodeProps, Position } from 'reactflow'
|
||||||
import { HANDLE_POSITIONS } from '@/lib/workflows/blocks/block-dimensions'
|
import { HANDLE_POSITIONS } from '@/lib/workflows/blocks/block-dimensions'
|
||||||
|
import {
|
||||||
|
buildCanonicalIndex,
|
||||||
|
evaluateSubBlockCondition,
|
||||||
|
isSubBlockFeatureEnabled,
|
||||||
|
isSubBlockVisibleForMode,
|
||||||
|
} from '@/lib/workflows/subblocks/visibility'
|
||||||
|
import { getDisplayValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/workflow-block'
|
||||||
import { getBlock } from '@/blocks'
|
import { getBlock } from '@/blocks'
|
||||||
|
import { SELECTOR_TYPES_HYDRATION_REQUIRED, type SubBlockConfig } from '@/blocks/types'
|
||||||
|
import { useVariablesStore } from '@/stores/panel/variables/store'
|
||||||
|
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
|
||||||
|
|
||||||
/** Execution status for blocks in preview mode */
|
/** Execution status for blocks in preview mode */
|
||||||
type ExecutionStatus = 'success' | 'error' | 'not-executed'
|
type ExecutionStatus = 'success' | 'error' | 'not-executed'
|
||||||
|
|
||||||
|
/** Subblock value structure matching workflow state */
|
||||||
|
interface SubBlockValueEntry {
|
||||||
|
value: unknown
|
||||||
|
}
|
||||||
|
|
||||||
interface WorkflowPreviewBlockData {
|
interface WorkflowPreviewBlockData {
|
||||||
type: string
|
type: string
|
||||||
name: string
|
name: string
|
||||||
@@ -18,12 +33,220 @@ interface WorkflowPreviewBlockData {
|
|||||||
isPreviewSelected?: boolean
|
isPreviewSelected?: boolean
|
||||||
/** Execution status for highlighting error/success states */
|
/** Execution status for highlighting error/success states */
|
||||||
executionStatus?: ExecutionStatus
|
executionStatus?: ExecutionStatus
|
||||||
|
/** Subblock values from the workflow state */
|
||||||
|
subBlockValues?: Record<string, SubBlockValueEntry | unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the raw value from a subblock value entry.
|
||||||
|
* Handles both wrapped ({ value: ... }) and unwrapped formats.
|
||||||
|
*/
|
||||||
|
function extractValue(entry: SubBlockValueEntry | unknown): unknown {
|
||||||
|
if (entry && typeof entry === 'object' && 'value' in entry) {
|
||||||
|
return (entry as SubBlockValueEntry).value
|
||||||
|
}
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SubBlockRowProps {
|
||||||
|
title: string
|
||||||
|
value?: string
|
||||||
|
subBlock?: SubBlockConfig
|
||||||
|
rawValue?: unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves dropdown/combobox value to its display label.
|
||||||
|
* Returns null if not a dropdown/combobox or no matching option found.
|
||||||
|
*/
|
||||||
|
function resolveDropdownLabel(
|
||||||
|
subBlock: SubBlockConfig | undefined,
|
||||||
|
rawValue: unknown
|
||||||
|
): string | null {
|
||||||
|
if (!subBlock || (subBlock.type !== 'dropdown' && subBlock.type !== 'combobox')) return null
|
||||||
|
if (!rawValue || typeof rawValue !== 'string') return null
|
||||||
|
|
||||||
|
const options = typeof subBlock.options === 'function' ? subBlock.options() : subBlock.options
|
||||||
|
if (!options) return null
|
||||||
|
|
||||||
|
const option = options.find((opt) =>
|
||||||
|
typeof opt === 'string' ? opt === rawValue : opt.id === rawValue
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!option) return null
|
||||||
|
return typeof option === 'string' ? option : option.label
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves workflow ID to workflow name using the workflow registry.
|
||||||
|
* Uses synchronous store access to avoid hook dependencies.
|
||||||
|
*/
|
||||||
|
function resolveWorkflowName(
|
||||||
|
subBlock: SubBlockConfig | undefined,
|
||||||
|
rawValue: unknown
|
||||||
|
): string | null {
|
||||||
|
if (subBlock?.type !== 'workflow-selector') return null
|
||||||
|
if (!rawValue || typeof rawValue !== 'string') return null
|
||||||
|
|
||||||
|
const workflowMap = useWorkflowRegistry.getState().workflows
|
||||||
|
return workflowMap[rawValue]?.name ?? null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type guard for variable assignments array
|
||||||
|
*/
|
||||||
|
function isVariableAssignmentsArray(
|
||||||
|
value: unknown
|
||||||
|
): value is Array<{ id?: string; variableId?: string; variableName?: string; value: unknown }> {
|
||||||
|
return (
|
||||||
|
Array.isArray(value) &&
|
||||||
|
value.length > 0 &&
|
||||||
|
value.every(
|
||||||
|
(item) =>
|
||||||
|
typeof item === 'object' &&
|
||||||
|
item !== null &&
|
||||||
|
('variableName' in item || 'variableId' in item)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves variables-input to display names.
|
||||||
|
* Uses synchronous store access to avoid hook dependencies.
|
||||||
|
*/
|
||||||
|
function resolveVariablesDisplay(
|
||||||
|
subBlock: SubBlockConfig | undefined,
|
||||||
|
rawValue: unknown
|
||||||
|
): string | null {
|
||||||
|
if (subBlock?.type !== 'variables-input') return null
|
||||||
|
if (!isVariableAssignmentsArray(rawValue)) return null
|
||||||
|
|
||||||
|
const variables = useVariablesStore.getState().variables
|
||||||
|
const variablesArray = Object.values(variables)
|
||||||
|
|
||||||
|
const names = rawValue
|
||||||
|
.map((a) => {
|
||||||
|
if (a.variableId) {
|
||||||
|
const variable = variablesArray.find((v) => v.id === a.variableId)
|
||||||
|
return variable?.name
|
||||||
|
}
|
||||||
|
if (a.variableName) return a.variableName
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
.filter((name): name is string => !!name)
|
||||||
|
|
||||||
|
if (names.length === 0) return null
|
||||||
|
if (names.length === 1) return names[0]
|
||||||
|
if (names.length === 2) return `${names[0]}, ${names[1]}`
|
||||||
|
return `${names[0]}, ${names[1]} +${names.length - 2}`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves tool-input to display names.
|
||||||
|
* Resolves built-in tools from block registry (no API needed).
|
||||||
|
*/
|
||||||
|
function resolveToolsDisplay(
|
||||||
|
subBlock: SubBlockConfig | undefined,
|
||||||
|
rawValue: unknown
|
||||||
|
): string | null {
|
||||||
|
if (subBlock?.type !== 'tool-input') return null
|
||||||
|
if (!Array.isArray(rawValue) || rawValue.length === 0) return null
|
||||||
|
|
||||||
|
const toolNames = rawValue
|
||||||
|
.map((tool: unknown) => {
|
||||||
|
if (!tool || typeof tool !== 'object') return null
|
||||||
|
const t = tool as Record<string, unknown>
|
||||||
|
|
||||||
|
// Priority 1: Use tool.title if already populated
|
||||||
|
if (t.title && typeof t.title === 'string') return t.title
|
||||||
|
|
||||||
|
// Priority 2: Extract from inline schema (legacy format)
|
||||||
|
const schema = t.schema as Record<string, unknown> | undefined
|
||||||
|
if (schema?.function && typeof schema.function === 'object') {
|
||||||
|
const fn = schema.function as Record<string, unknown>
|
||||||
|
if (fn.name && typeof fn.name === 'string') return fn.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priority 3: Extract from OpenAI function format
|
||||||
|
const fn = t.function as Record<string, unknown> | undefined
|
||||||
|
if (fn?.name && typeof fn.name === 'string') return fn.name
|
||||||
|
|
||||||
|
// Priority 4: Resolve built-in tool blocks from registry
|
||||||
|
if (
|
||||||
|
typeof t.type === 'string' &&
|
||||||
|
t.type !== 'custom-tool' &&
|
||||||
|
t.type !== 'mcp' &&
|
||||||
|
t.type !== 'workflow' &&
|
||||||
|
t.type !== 'workflow_input'
|
||||||
|
) {
|
||||||
|
const blockConfig = getBlock(t.type)
|
||||||
|
if (blockConfig?.name) return blockConfig.name
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
.filter((name): name is string => !!name)
|
||||||
|
|
||||||
|
if (toolNames.length === 0) return null
|
||||||
|
if (toolNames.length === 1) return toolNames[0]
|
||||||
|
if (toolNames.length === 2) return `${toolNames[0]}, ${toolNames[1]}`
|
||||||
|
return `${toolNames[0]}, ${toolNames[1]} +${toolNames.length - 2}`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a single subblock row with title and optional value.
|
||||||
|
* Matches the SubBlockRow component in WorkflowBlock.
|
||||||
|
* - Masks password fields with bullets
|
||||||
|
* - Resolves dropdown/combobox labels
|
||||||
|
* - Resolves workflow names from registry
|
||||||
|
* - Resolves variable names from store
|
||||||
|
* - Resolves tool names from block registry
|
||||||
|
* - Shows '-' for other selector types that need hydration
|
||||||
|
*/
|
||||||
|
function SubBlockRow({ title, value, subBlock, rawValue }: SubBlockRowProps) {
|
||||||
|
// Mask password fields
|
||||||
|
const isPasswordField = subBlock?.password === true
|
||||||
|
const maskedValue = isPasswordField && value && value !== '-' ? '•••' : null
|
||||||
|
|
||||||
|
// Resolve various display names (synchronous access, matching WorkflowBlock priority)
|
||||||
|
const dropdownLabel = resolveDropdownLabel(subBlock, rawValue)
|
||||||
|
const variablesDisplay = resolveVariablesDisplay(subBlock, rawValue)
|
||||||
|
const toolsDisplay = resolveToolsDisplay(subBlock, rawValue)
|
||||||
|
const workflowName = resolveWorkflowName(subBlock, rawValue)
|
||||||
|
|
||||||
|
// Check if this is a selector type that needs hydration (show '-' for raw IDs)
|
||||||
|
const isSelectorType = subBlock?.type && SELECTOR_TYPES_HYDRATION_REQUIRED.includes(subBlock.type)
|
||||||
|
|
||||||
|
// Compute final display value matching WorkflowBlock logic
|
||||||
|
// Priority order matches WorkflowBlock: masked > hydrated names > selector fallback > raw value
|
||||||
|
const hydratedName = dropdownLabel || variablesDisplay || toolsDisplay || workflowName
|
||||||
|
const displayValue = maskedValue || hydratedName || (isSelectorType && value ? '-' : value)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex items-center gap-[8px]'>
|
||||||
|
<span
|
||||||
|
className='min-w-0 truncate text-[14px] text-[var(--text-tertiary)] capitalize'
|
||||||
|
title={title}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
{displayValue !== undefined && (
|
||||||
|
<span
|
||||||
|
className='flex-1 truncate text-right text-[14px] text-[var(--text-primary)]'
|
||||||
|
title={displayValue}
|
||||||
|
>
|
||||||
|
{displayValue}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preview block component for workflow visualization.
|
* Preview block component for workflow visualization.
|
||||||
* Renders block header, subblocks skeleton, and handles without
|
* Renders block header, subblock values, and handles without
|
||||||
* hooks, store subscriptions, or interactive features.
|
* hooks, store subscriptions, or interactive features.
|
||||||
|
* Matches the visual structure of WorkflowBlock exactly.
|
||||||
*/
|
*/
|
||||||
function WorkflowPreviewBlockInner({ data }: NodeProps<WorkflowPreviewBlockData>) {
|
function WorkflowPreviewBlockInner({ data }: NodeProps<WorkflowPreviewBlockData>) {
|
||||||
const {
|
const {
|
||||||
@@ -34,21 +257,111 @@ function WorkflowPreviewBlockInner({ data }: NodeProps<WorkflowPreviewBlockData>
|
|||||||
enabled = true,
|
enabled = true,
|
||||||
isPreviewSelected = false,
|
isPreviewSelected = false,
|
||||||
executionStatus,
|
executionStatus,
|
||||||
|
subBlockValues,
|
||||||
} = data
|
} = data
|
||||||
|
|
||||||
const blockConfig = getBlock(type)
|
const blockConfig = getBlock(type)
|
||||||
|
|
||||||
|
const canonicalIndex = useMemo(
|
||||||
|
() => buildCanonicalIndex(blockConfig?.subBlocks || []),
|
||||||
|
[blockConfig?.subBlocks]
|
||||||
|
)
|
||||||
|
|
||||||
|
const rawValues = useMemo(() => {
|
||||||
|
if (!subBlockValues) return {}
|
||||||
|
return Object.entries(subBlockValues).reduce<Record<string, unknown>>((acc, [key, entry]) => {
|
||||||
|
acc[key] = extractValue(entry)
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
}, [subBlockValues])
|
||||||
|
|
||||||
const visibleSubBlocks = useMemo(() => {
|
const visibleSubBlocks = useMemo(() => {
|
||||||
if (!blockConfig?.subBlocks) return []
|
if (!blockConfig?.subBlocks) return []
|
||||||
|
|
||||||
|
const isStarterOrTrigger =
|
||||||
|
blockConfig.category === 'triggers' || type === 'starter' || isTrigger
|
||||||
|
|
||||||
return blockConfig.subBlocks.filter((subBlock) => {
|
return blockConfig.subBlocks.filter((subBlock) => {
|
||||||
if (subBlock.hidden) return false
|
if (subBlock.hidden) return false
|
||||||
if (subBlock.hideFromPreview) return false
|
if (subBlock.hideFromPreview) return false
|
||||||
if (subBlock.mode === 'trigger' && blockConfig.category !== 'triggers') return false
|
if (!isSubBlockFeatureEnabled(subBlock)) return false
|
||||||
if (subBlock.mode === 'advanced') return false
|
|
||||||
return true
|
// Handle trigger mode visibility
|
||||||
|
if (subBlock.mode === 'trigger' && !isStarterOrTrigger) return false
|
||||||
|
|
||||||
|
// Check advanced mode visibility
|
||||||
|
if (!isSubBlockVisibleForMode(subBlock, false, canonicalIndex, rawValues, undefined)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check condition visibility
|
||||||
|
if (!subBlock.condition) return true
|
||||||
|
return evaluateSubBlockCondition(subBlock.condition, rawValues)
|
||||||
})
|
})
|
||||||
}, [blockConfig?.subBlocks])
|
}, [blockConfig?.subBlocks, blockConfig?.category, type, isTrigger, canonicalIndex, rawValues])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute condition rows for condition blocks
|
||||||
|
*/
|
||||||
|
const conditionRows = useMemo(() => {
|
||||||
|
if (type !== 'condition') return []
|
||||||
|
|
||||||
|
const conditionsValue = rawValues.conditions
|
||||||
|
const raw = typeof conditionsValue === 'string' ? conditionsValue : undefined
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (raw) {
|
||||||
|
const parsed = JSON.parse(raw) as unknown
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
return parsed.map((item: unknown, index: number) => {
|
||||||
|
const conditionItem = item as { id?: string; value?: unknown }
|
||||||
|
const title = index === 0 ? 'if' : index === parsed.length - 1 ? 'else' : 'else if'
|
||||||
|
return {
|
||||||
|
id: conditionItem?.id ?? `cond-${index}`,
|
||||||
|
title,
|
||||||
|
value: typeof conditionItem?.value === 'string' ? conditionItem.value : '',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Failed to parse, use fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{ id: 'if', title: 'if', value: '' },
|
||||||
|
{ id: 'else', title: 'else', value: '' },
|
||||||
|
]
|
||||||
|
}, [type, rawValues])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute router rows for router_v2 blocks
|
||||||
|
*/
|
||||||
|
const routerRows = useMemo(() => {
|
||||||
|
if (type !== 'router_v2') return []
|
||||||
|
|
||||||
|
const routesValue = rawValues.routes
|
||||||
|
const raw = typeof routesValue === 'string' ? routesValue : undefined
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (raw) {
|
||||||
|
const parsed = JSON.parse(raw) as unknown
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
return parsed.map((item: unknown, index: number) => {
|
||||||
|
const routeItem = item as { id?: string; value?: string }
|
||||||
|
return {
|
||||||
|
id: routeItem?.id ?? `route${index + 1}`,
|
||||||
|
value: routeItem?.value ?? '',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Failed to parse, use fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
return [{ id: 'route1', value: '' }]
|
||||||
|
}, [type, rawValues])
|
||||||
|
|
||||||
if (!blockConfig) {
|
if (!blockConfig) {
|
||||||
return null
|
return null
|
||||||
@@ -57,8 +370,14 @@ function WorkflowPreviewBlockInner({ data }: NodeProps<WorkflowPreviewBlockData>
|
|||||||
const IconComponent = blockConfig.icon
|
const IconComponent = blockConfig.icon
|
||||||
const isStarterOrTrigger = blockConfig.category === 'triggers' || type === 'starter' || isTrigger
|
const isStarterOrTrigger = blockConfig.category === 'triggers' || type === 'starter' || isTrigger
|
||||||
|
|
||||||
|
const shouldShowDefaultHandles = !isStarterOrTrigger
|
||||||
const hasSubBlocks = visibleSubBlocks.length > 0
|
const hasSubBlocks = visibleSubBlocks.length > 0
|
||||||
const showErrorRow = !isStarterOrTrigger
|
const hasContentBelowHeader =
|
||||||
|
type === 'condition'
|
||||||
|
? conditionRows.length > 0 || shouldShowDefaultHandles
|
||||||
|
: type === 'router_v2'
|
||||||
|
? routerRows.length > 0 || shouldShowDefaultHandles
|
||||||
|
: hasSubBlocks || shouldShowDefaultHandles
|
||||||
|
|
||||||
const horizontalHandleClass = '!border-none !bg-[var(--surface-7)] !h-5 !w-[7px] !rounded-[2px]'
|
const horizontalHandleClass = '!border-none !bg-[var(--surface-7)] !h-5 !w-[7px] !rounded-[2px]'
|
||||||
const verticalHandleClass = '!border-none !bg-[var(--surface-7)] !h-[7px] !w-5 !rounded-[2px]'
|
const verticalHandleClass = '!border-none !bg-[var(--surface-7)] !h-[7px] !w-5 !rounded-[2px]'
|
||||||
@@ -67,7 +386,7 @@ function WorkflowPreviewBlockInner({ data }: NodeProps<WorkflowPreviewBlockData>
|
|||||||
const hasSuccess = executionStatus === 'success'
|
const hasSuccess = executionStatus === 'success'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative w-[250px] select-none rounded-[8px] border border-[var(--border)] bg-[var(--surface-2)]'>
|
<div className='relative w-[250px] select-none rounded-[8px] border border-[var(--border-1)] bg-[var(--surface-2)]'>
|
||||||
{/* Selection ring overlay (takes priority over execution rings) */}
|
{/* Selection ring overlay (takes priority over execution rings) */}
|
||||||
{isPreviewSelected && (
|
{isPreviewSelected && (
|
||||||
<div className='pointer-events-none absolute inset-0 z-40 rounded-[8px] ring-[1.75px] ring-[var(--brand-secondary)]' />
|
<div className='pointer-events-none absolute inset-0 z-40 rounded-[8px] ring-[1.75px] ring-[var(--brand-secondary)]' />
|
||||||
@@ -82,7 +401,7 @@ function WorkflowPreviewBlockInner({ data }: NodeProps<WorkflowPreviewBlockData>
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Target handle - not shown for triggers/starters */}
|
{/* Target handle - not shown for triggers/starters */}
|
||||||
{!isStarterOrTrigger && (
|
{shouldShowDefaultHandles && (
|
||||||
<Handle
|
<Handle
|
||||||
type='target'
|
type='target'
|
||||||
position={horizontalHandles ? Position.Left : Position.Top}
|
position={horizontalHandles ? Position.Left : Position.Top}
|
||||||
@@ -96,49 +415,67 @@ function WorkflowPreviewBlockInner({ data }: NodeProps<WorkflowPreviewBlockData>
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Header */}
|
{/* Header - matches WorkflowBlock structure */}
|
||||||
<div
|
<div
|
||||||
className={`flex items-center gap-[10px] p-[8px] ${hasSubBlocks || showErrorRow ? 'border-[var(--divider)] border-b' : ''}`}
|
className={`flex items-center justify-between p-[8px] ${hasContentBelowHeader ? 'border-[var(--border-1)] border-b' : ''}`}
|
||||||
>
|
>
|
||||||
<div
|
<div className='relative z-10 flex min-w-0 flex-1 items-center gap-[10px]'>
|
||||||
className='flex h-[24px] w-[24px] flex-shrink-0 items-center justify-center rounded-[6px]'
|
<div
|
||||||
style={{ background: enabled ? blockConfig.bgColor : 'gray' }}
|
className='flex h-[24px] w-[24px] flex-shrink-0 items-center justify-center rounded-[6px]'
|
||||||
>
|
style={{ background: enabled ? blockConfig.bgColor : 'gray' }}
|
||||||
<IconComponent className='h-[16px] w-[16px] text-white' />
|
>
|
||||||
|
<IconComponent className='h-[16px] w-[16px] text-white' />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
className={`truncate font-medium text-[16px] ${!enabled ? 'text-[var(--text-muted)]' : ''}`}
|
||||||
|
title={name}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span
|
|
||||||
className={`truncate font-medium text-[16px] ${!enabled ? 'text-[#808080]' : ''}`}
|
|
||||||
title={name}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Subblocks skeleton */}
|
{/* Content area with subblocks */}
|
||||||
{(hasSubBlocks || showErrorRow) && (
|
{hasContentBelowHeader && (
|
||||||
<div className='flex flex-col gap-[8px] p-[8px]'>
|
<div className='flex flex-col gap-[8px] p-[8px]'>
|
||||||
{visibleSubBlocks.slice(0, 4).map((subBlock) => (
|
{type === 'condition' ? (
|
||||||
<div key={subBlock.id} className='flex items-center gap-[8px]'>
|
// Condition block: render condition rows
|
||||||
<span className='min-w-0 truncate text-[14px] text-[var(--text-tertiary)] capitalize'>
|
conditionRows.map((cond) => (
|
||||||
{subBlock.title ?? subBlock.id}
|
<SubBlockRow key={cond.id} title={cond.title} value={getDisplayValue(cond.value)} />
|
||||||
</span>
|
))
|
||||||
<span className='flex-1 truncate text-right text-[14px] text-[var(--white)]'>-</span>
|
) : type === 'router_v2' ? (
|
||||||
</div>
|
// Router block: render context + route rows
|
||||||
))}
|
<>
|
||||||
{visibleSubBlocks.length > 4 && (
|
<SubBlockRow
|
||||||
<div className='flex items-center gap-[8px]'>
|
key='context'
|
||||||
<span className='text-[14px] text-[var(--text-tertiary)]'>
|
title='Context'
|
||||||
+{visibleSubBlocks.length - 4} more
|
value={getDisplayValue(rawValues.context)}
|
||||||
</span>
|
/>
|
||||||
</div>
|
{routerRows.map((route, index) => (
|
||||||
)}
|
<SubBlockRow
|
||||||
{showErrorRow && (
|
key={route.id}
|
||||||
<div className='flex items-center gap-[8px]'>
|
title={`Route ${index + 1}`}
|
||||||
<span className='min-w-0 truncate text-[14px] text-[var(--text-tertiary)] capitalize'>
|
value={getDisplayValue(route.value)}
|
||||||
error
|
/>
|
||||||
</span>
|
))}
|
||||||
</div>
|
</>
|
||||||
|
) : (
|
||||||
|
// Standard blocks: render visible subblocks
|
||||||
|
visibleSubBlocks.map((subBlock) => {
|
||||||
|
const rawValue = rawValues[subBlock.id]
|
||||||
|
return (
|
||||||
|
<SubBlockRow
|
||||||
|
key={subBlock.id}
|
||||||
|
title={subBlock.title ?? subBlock.id}
|
||||||
|
value={getDisplayValue(rawValue)}
|
||||||
|
subBlock={subBlock}
|
||||||
|
rawValue={rawValue}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
)}
|
)}
|
||||||
|
{/* Error row for non-trigger blocks */}
|
||||||
|
{shouldShowDefaultHandles && <SubBlockRow title='error' />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -162,16 +499,47 @@ function shouldSkipPreviewBlockRender(
|
|||||||
prevProps: NodeProps<WorkflowPreviewBlockData>,
|
prevProps: NodeProps<WorkflowPreviewBlockData>,
|
||||||
nextProps: NodeProps<WorkflowPreviewBlockData>
|
nextProps: NodeProps<WorkflowPreviewBlockData>
|
||||||
): boolean {
|
): boolean {
|
||||||
return (
|
// Check primitive props first (fast path)
|
||||||
prevProps.id === nextProps.id &&
|
if (
|
||||||
prevProps.data.type === nextProps.data.type &&
|
prevProps.id !== nextProps.id ||
|
||||||
prevProps.data.name === nextProps.data.name &&
|
prevProps.data.type !== nextProps.data.type ||
|
||||||
prevProps.data.isTrigger === nextProps.data.isTrigger &&
|
prevProps.data.name !== nextProps.data.name ||
|
||||||
prevProps.data.horizontalHandles === nextProps.data.horizontalHandles &&
|
prevProps.data.isTrigger !== nextProps.data.isTrigger ||
|
||||||
prevProps.data.enabled === nextProps.data.enabled &&
|
prevProps.data.horizontalHandles !== nextProps.data.horizontalHandles ||
|
||||||
prevProps.data.isPreviewSelected === nextProps.data.isPreviewSelected &&
|
prevProps.data.enabled !== nextProps.data.enabled ||
|
||||||
prevProps.data.executionStatus === nextProps.data.executionStatus
|
prevProps.data.isPreviewSelected !== nextProps.data.isPreviewSelected ||
|
||||||
)
|
prevProps.data.executionStatus !== nextProps.data.executionStatus
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare subBlockValues by reference first
|
||||||
|
const prevValues = prevProps.data.subBlockValues
|
||||||
|
const nextValues = nextProps.data.subBlockValues
|
||||||
|
|
||||||
|
if (prevValues === nextValues) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!prevValues || !nextValues) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shallow compare keys and values
|
||||||
|
const prevKeys = Object.keys(prevValues)
|
||||||
|
const nextKeys = Object.keys(nextValues)
|
||||||
|
|
||||||
|
if (prevKeys.length !== nextKeys.length) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key of prevKeys) {
|
||||||
|
if (prevValues[key] !== nextValues[key]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export const WorkflowPreviewBlock = memo(WorkflowPreviewBlockInner, shouldSkipPreviewBlockRender)
|
export const WorkflowPreviewBlock = memo(WorkflowPreviewBlockInner, shouldSkipPreviewBlockRender)
|
||||||
|
|||||||
@@ -347,6 +347,7 @@ export function WorkflowPreview({
|
|||||||
enabled: block.enabled ?? true,
|
enabled: block.enabled ?? true,
|
||||||
isPreviewSelected: isSelected,
|
isPreviewSelected: isSelected,
|
||||||
executionStatus,
|
executionStatus,
|
||||||
|
subBlockValues: block.subBlocks,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ export function SocketProvider({ children, user }: SocketProviderProps) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
useWorkflowStore.setState({
|
useWorkflowStore.getState().replaceWorkflowState({
|
||||||
blocks: workflowState.blocks || {},
|
blocks: workflowState.blocks || {},
|
||||||
edges: workflowState.edges || [],
|
edges: workflowState.edges || [],
|
||||||
loops: workflowState.loops || {},
|
loops: workflowState.loops || {},
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
} from '@/lib/workflows/schedules/utils'
|
} from '@/lib/workflows/schedules/utils'
|
||||||
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
||||||
import type { ExecutionMetadata } from '@/executor/execution/types'
|
import type { ExecutionMetadata } from '@/executor/execution/types'
|
||||||
import type { ExecutionResult } from '@/executor/types'
|
import { hasExecutionResult } from '@/executor/utils/errors'
|
||||||
import { MAX_CONSECUTIVE_FAILURES } from '@/triggers/constants'
|
import { MAX_CONSECUTIVE_FAILURES } from '@/triggers/constants'
|
||||||
|
|
||||||
const logger = createLogger('TriggerScheduleExecution')
|
const logger = createLogger('TriggerScheduleExecution')
|
||||||
@@ -231,8 +231,7 @@ async function runWorkflowExecution({
|
|||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error(`[${requestId}] Early failure in scheduled workflow ${payload.workflowId}`, error)
|
logger.error(`[${requestId}] Early failure in scheduled workflow ${payload.workflowId}`, error)
|
||||||
|
|
||||||
const errorWithResult = error as { executionResult?: ExecutionResult }
|
const executionResult = hasExecutionResult(error) ? error.executionResult : undefined
|
||||||
const executionResult = errorWithResult?.executionResult
|
|
||||||
const { traceSpans } = executionResult ? buildTraceSpans(executionResult) : { traceSpans: [] }
|
const { traceSpans } = executionResult ? buildTraceSpans(executionResult) : { traceSpans: [] }
|
||||||
|
|
||||||
await loggingSession.safeCompleteWithError({
|
await loggingSession.safeCompleteWithError({
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { loadDeployedWorkflowState } from '@/lib/workflows/persistence/utils'
|
|||||||
import { getWorkflowById } from '@/lib/workflows/utils'
|
import { getWorkflowById } from '@/lib/workflows/utils'
|
||||||
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
||||||
import type { ExecutionMetadata } from '@/executor/execution/types'
|
import type { ExecutionMetadata } from '@/executor/execution/types'
|
||||||
import type { ExecutionResult } from '@/executor/types'
|
import { hasExecutionResult } from '@/executor/utils/errors'
|
||||||
import { safeAssign } from '@/tools/safe-assign'
|
import { safeAssign } from '@/tools/safe-assign'
|
||||||
import { getTrigger, isTriggerValid } from '@/triggers'
|
import { getTrigger, isTriggerValid } from '@/triggers'
|
||||||
|
|
||||||
@@ -578,12 +578,13 @@ async function executeWebhookJobInternal(
|
|||||||
deploymentVersionId,
|
deploymentVersionId,
|
||||||
})
|
})
|
||||||
|
|
||||||
const errorWithResult = error as { executionResult?: ExecutionResult }
|
const executionResult = hasExecutionResult(error)
|
||||||
const executionResult = errorWithResult?.executionResult || {
|
? error.executionResult
|
||||||
success: false,
|
: {
|
||||||
output: {},
|
success: false,
|
||||||
logs: [],
|
output: {},
|
||||||
}
|
logs: [],
|
||||||
|
}
|
||||||
const { traceSpans } = buildTraceSpans(executionResult)
|
const { traceSpans } = buildTraceSpans(executionResult)
|
||||||
|
|
||||||
await loggingSession.safeCompleteWithError({
|
await loggingSession.safeCompleteWithError({
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { PauseResumeManager } from '@/lib/workflows/executor/human-in-the-loop-m
|
|||||||
import { getWorkflowById } from '@/lib/workflows/utils'
|
import { getWorkflowById } from '@/lib/workflows/utils'
|
||||||
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
||||||
import type { ExecutionMetadata } from '@/executor/execution/types'
|
import type { ExecutionMetadata } from '@/executor/execution/types'
|
||||||
import type { ExecutionResult } from '@/executor/types'
|
import { hasExecutionResult } from '@/executor/utils/errors'
|
||||||
import type { CoreTriggerType } from '@/stores/logs/filters/types'
|
import type { CoreTriggerType } from '@/stores/logs/filters/types'
|
||||||
|
|
||||||
const logger = createLogger('TriggerWorkflowExecution')
|
const logger = createLogger('TriggerWorkflowExecution')
|
||||||
@@ -160,8 +160,7 @@ export async function executeWorkflowJob(payload: WorkflowExecutionPayload) {
|
|||||||
executionId,
|
executionId,
|
||||||
})
|
})
|
||||||
|
|
||||||
const errorWithResult = error as { executionResult?: ExecutionResult }
|
const executionResult = hasExecutionResult(error) ? error.executionResult : undefined
|
||||||
const executionResult = errorWithResult?.executionResult
|
|
||||||
const { traceSpans } = executionResult ? buildTraceSpans(executionResult) : { traceSpans: [] }
|
const { traceSpans } = executionResult ? buildTraceSpans(executionResult) : { traceSpans: [] }
|
||||||
|
|
||||||
await loggingSession.safeCompleteWithError({
|
await loggingSession.safeCompleteWithError({
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Copilot supports slash commands that trigger specialized capabilities:
|
|||||||
|
|
||||||
- `/fast` — uses a faster model for quick responses when you need speed over depth
|
- `/fast` — uses a faster model for quick responses when you need speed over depth
|
||||||
- `/research` — performs multi-step web research on a topic, synthesizing results from multiple sources
|
- `/research` — performs multi-step web research on a topic, synthesizing results from multiple sources
|
||||||
- `/actions` — enables agentic mode where Copilot can take actions on your behalf, like modifying blocks or creating workflows
|
- `/actions` — lets Copilot directly use your connected integrations as tools, like reading your Gmail, sending Slack messages, or querying your database—all outside the context of a workflow
|
||||||
- `/search` — searches the web for relevant information
|
- `/search` — searches the web for relevant information
|
||||||
- `/read` — reads and extracts content from a URL
|
- `/read` — reads and extracts content from a URL
|
||||||
- `/scrape` — scrapes structured data from web pages
|
- `/scrape` — scrapes structured data from web pages
|
||||||
|
|||||||
31
apps/sim/executor/errors/child-workflow-error.ts
Normal file
31
apps/sim/executor/errors/child-workflow-error.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import type { TraceSpan } from '@/lib/logs/types'
|
||||||
|
import type { ExecutionResult } from '@/executor/types'
|
||||||
|
|
||||||
|
interface ChildWorkflowErrorOptions {
|
||||||
|
message: string
|
||||||
|
childWorkflowName: string
|
||||||
|
childTraceSpans?: TraceSpan[]
|
||||||
|
executionResult?: ExecutionResult
|
||||||
|
cause?: Error
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error raised when a child workflow execution fails.
|
||||||
|
*/
|
||||||
|
export class ChildWorkflowError extends Error {
|
||||||
|
readonly childTraceSpans: TraceSpan[]
|
||||||
|
readonly childWorkflowName: string
|
||||||
|
readonly executionResult?: ExecutionResult
|
||||||
|
|
||||||
|
constructor(options: ChildWorkflowErrorOptions) {
|
||||||
|
super(options.message, { cause: options.cause })
|
||||||
|
this.name = 'ChildWorkflowError'
|
||||||
|
this.childWorkflowName = options.childWorkflowName
|
||||||
|
this.childTraceSpans = options.childTraceSpans ?? []
|
||||||
|
this.executionResult = options.executionResult
|
||||||
|
}
|
||||||
|
|
||||||
|
static isChildWorkflowError(error: unknown): error is ChildWorkflowError {
|
||||||
|
return error instanceof ChildWorkflowError
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
isSentinelBlockType,
|
isSentinelBlockType,
|
||||||
} from '@/executor/constants'
|
} from '@/executor/constants'
|
||||||
import type { DAGNode } from '@/executor/dag/builder'
|
import type { DAGNode } from '@/executor/dag/builder'
|
||||||
|
import { ChildWorkflowError } from '@/executor/errors/child-workflow-error'
|
||||||
import type { BlockStateWriter, ContextExtensions } from '@/executor/execution/types'
|
import type { BlockStateWriter, ContextExtensions } from '@/executor/execution/types'
|
||||||
import {
|
import {
|
||||||
generatePauseContextId,
|
generatePauseContextId,
|
||||||
@@ -213,24 +214,26 @@ export class BlockExecutor {
|
|||||||
? resolvedInputs
|
? resolvedInputs
|
||||||
: ((block.config?.params as Record<string, any> | undefined) ?? {})
|
: ((block.config?.params as Record<string, any> | undefined) ?? {})
|
||||||
|
|
||||||
|
const errorOutput: NormalizedBlockOutput = {
|
||||||
|
error: errorMessage,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ChildWorkflowError.isChildWorkflowError(error)) {
|
||||||
|
errorOutput.childTraceSpans = error.childTraceSpans
|
||||||
|
errorOutput.childWorkflowName = error.childWorkflowName
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state.setBlockOutput(node.id, errorOutput, duration)
|
||||||
|
|
||||||
if (blockLog) {
|
if (blockLog) {
|
||||||
blockLog.endedAt = new Date().toISOString()
|
blockLog.endedAt = new Date().toISOString()
|
||||||
blockLog.durationMs = duration
|
blockLog.durationMs = duration
|
||||||
blockLog.success = false
|
blockLog.success = false
|
||||||
blockLog.error = errorMessage
|
blockLog.error = errorMessage
|
||||||
blockLog.input = input
|
blockLog.input = input
|
||||||
|
blockLog.output = this.filterOutputForLog(block, errorOutput)
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorOutput: NormalizedBlockOutput = {
|
|
||||||
error: errorMessage,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error && typeof error === 'object' && 'childTraceSpans' in error) {
|
|
||||||
errorOutput.childTraceSpans = (error as any).childTraceSpans
|
|
||||||
}
|
|
||||||
|
|
||||||
this.state.setBlockOutput(node.id, errorOutput, duration)
|
|
||||||
|
|
||||||
logger.error(
|
logger.error(
|
||||||
phase === 'input_resolution' ? 'Failed to resolve block inputs' : 'Block execution failed',
|
phase === 'input_resolution' ? 'Failed to resolve block inputs' : 'Block execution failed',
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user