Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/sim/app/api/auth/oauth/connections/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { jwtDecode } from 'jwt-decode'
import { type NextRequest, NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console/logger'
import { generateServerUUID } from '@/lib/uuid'
import { db } from '@/db'
import { account, user } from '@/db/schema'

Expand All @@ -18,7 +19,7 @@ interface GoogleIdToken {
* Get all OAuth connections for the current user
*/
export async function GET(request: NextRequest) {
const requestId = crypto.randomUUID().slice(0, 8)
const requestId = generateServerUUID().slice(0, 8)

try {
// Get the session
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/app/api/auth/oauth/credentials/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { jwtDecode } from 'jwt-decode'
import { type NextRequest, NextResponse } from 'next/server'
import { checkHybridAuth } from '@/lib/auth/hybrid'
import { createLogger } from '@/lib/logs/console/logger'
import { generateSecureUUID } from '@/lib/uuid'
import type { OAuthService } from '@/lib/oauth/oauth'
import { parseProvider } from '@/lib/oauth/oauth'
import { getUserEntityPermissions } from '@/lib/permissions/utils'
Expand All @@ -23,7 +24,7 @@ interface GoogleIdToken {
* Get credentials for a specific provider
*/
export async function GET(request: NextRequest) {
const requestId = crypto.randomUUID().slice(0, 8)
const requestId = generateSecureUUID().slice(0, 8)

try {
// Get query params
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/app/api/auth/oauth/disconnect/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { and, eq, like, or } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console/logger'
import { generateServerUUID } from '@/lib/uuid'
import { db } from '@/db'
import { account } from '@/db/schema'

Expand All @@ -13,7 +14,7 @@ const logger = createLogger('OAuthDisconnectAPI')
* Disconnect an OAuth provider for the current user
*/
export async function POST(request: NextRequest) {
const requestId = crypto.randomUUID().slice(0, 8)
const requestId = generateServerUUID().slice(0, 8)

try {
// Get the session
Expand Down
5 changes: 3 additions & 2 deletions apps/sim/app/api/auth/oauth/token/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { type NextRequest, NextResponse } from 'next/server'
import { authorizeCredentialUse } from '@/lib/auth/credential-access'
import { checkHybridAuth } from '@/lib/auth/hybrid'
import { createLogger } from '@/lib/logs/console/logger'
import { generateSecureUUID } from '@/lib/uuid'
import { getCredential, refreshTokenIfNeeded } from '@/app/api/auth/oauth/utils'

export const dynamic = 'force-dynamic'
Expand All @@ -14,7 +15,7 @@ const logger = createLogger('OAuthTokenAPI')
* and workflow-based authentication (for server-side requests)
*/
export async function POST(request: NextRequest) {
const requestId = crypto.randomUUID().slice(0, 8)
const requestId = generateSecureUUID().slice(0, 8)

logger.info(`[${requestId}] OAuth token API POST request received`)

Expand Down Expand Up @@ -59,7 +60,7 @@ export async function POST(request: NextRequest) {
* Get the access token for a specific credential
*/
export async function GET(request: NextRequest) {
const requestId = crypto.randomUUID().slice(0, 8) // Short request ID for correlation
const requestId = generateSecureUUID().slice(0, 8) // Short request ID for correlation

try {
// Get the credential ID from the query params
Expand Down
12 changes: 11 additions & 1 deletion apps/sim/app/api/tools/postgresql/query/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
import { type NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
import { createLogger } from '@/lib/logs/console/logger'
import { createPostgresConnection, executeQuery } from '@/app/api/tools/postgresql/utils'
import { createPostgresConnection, executeQuery, validateQuery } from '@/app/api/tools/postgresql/utils'

const logger = createLogger('PostgreSQLQueryAPI')

Expand All @@ -27,6 +27,16 @@ export async function POST(request: NextRequest) {
`[${requestId}] Executing PostgreSQL query on ${params.host}:${params.port}/${params.database}`
)

// Validate query for security
const queryValidation = validateQuery(params.query)
if (!queryValidation.isValid) {
logger.warn(`[${requestId}] Query validation failed: ${queryValidation.error}`)
return NextResponse.json(
{ error: `Query validation failed: ${queryValidation.error}` },
{ status: 400 }
)
}

const sql = createPostgresConnection({
host: params.host,
port: params.port,
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/app/api/users/me/api-keys/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { and, eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { getSession } from '@/lib/auth'
import { createLogger } from '@/lib/logs/console/logger'
import { generateSecureUUID } from '@/lib/uuid'
import { db } from '@/db'
import { apiKey } from '@/db/schema'

Expand All @@ -12,7 +13,7 @@ export async function DELETE(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) {
const requestId = crypto.randomUUID().slice(0, 8)
const requestId = generateSecureUUID().slice(0, 8)
const { id } = await params

try {
Expand Down
97 changes: 91 additions & 6 deletions apps/sim/app/global-error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,105 @@
import { useEffect } from 'react'
import * as Sentry from '@sentry/nextjs'
import NextError from 'next/error'
import { createLogger } from '@/lib/logs/console/logger'

export default function GlobalError({ error }: { error: Error & { digest?: string } }) {
const logger = createLogger('GlobalError')

export default function GlobalError({
error,
reset
}: {
error: Error & { digest?: string }
reset?: () => void
}) {
useEffect(() => {
// Enhanced error logging for debugging
logger.error('Global error occurred:', {
message: error.message,
name: error.name,
stack: error.stack,
digest: error.digest,
// Additional context for crypto-related errors
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'N/A',
isSecureContext: typeof window !== 'undefined' ? window.isSecureContext : 'N/A',
location: typeof window !== 'undefined' ? window.location.href : 'N/A',
})

// Check if this is a crypto-related error and provide specific guidance
if (error.message?.includes('randomUUID') || error.message?.includes('crypto')) {
logger.warn('Crypto API error detected. This may be due to insecure context (HTTP instead of HTTPS)')
}

Sentry.captureException(error)
}, [error])

return (
<html lang='en'>
<body>
{/* `NextError` is the default Next.js error page component. Its type
definition requires a `statusCode` prop. However, since the App Router
does not expose status codes for errors, we simply pass 0 to render a
generic error message. */}
<NextError statusCode={0} />
<div style={{
padding: '2rem',
textAlign: 'center',
fontFamily: 'system-ui, sans-serif',
minHeight: '100vh',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
backgroundColor: '#1a1a1a',
color: '#white'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: Invalid CSS color value: '#white' should be 'white'

Suggested change
color: '#white'
color: 'white'

}}>
<h1 style={{ color: '#ef4444', marginBottom: '1rem' }}>
Application Error
</h1>
<p style={{ marginBottom: '1rem', color: '#a3a3a3' }}>
A client-side exception has occurred. This error has been logged for investigation.
</p>
{error.message?.includes('randomUUID') || error.message?.includes('crypto') ? (
<div style={{
backgroundColor: '#374151',
padding: '1rem',
borderRadius: '0.5rem',
marginBottom: '1rem',
color: '#fbbf24'
}}>
<p><strong>Tip:</strong> This error may be resolved by:</p>
<ul style={{ textAlign: 'left', margin: '0.5rem 0' }}>
<li>Accessing the application via HTTPS</li>
<li>Using localhost instead of other local IP addresses</li>
<li>Checking your browser security settings</li>
</ul>
</div>
) : null}
{reset && (
<button
onClick={reset}
style={{
padding: '0.5rem 1rem',
backgroundColor: '#3b82f6',
color: 'white',
border: 'none',
borderRadius: '0.25rem',
cursor: 'pointer',
fontSize: '1rem'
}}
>
Try Again
</button>
)}
<details style={{ marginTop: '2rem', textAlign: 'left', maxWidth: '600px', margin: '2rem auto 0' }}>
<summary style={{ cursor: 'pointer', marginBottom: '1rem' }}>Error Details</summary>
<pre style={{
backgroundColor: '#374151',
padding: '1rem',
borderRadius: '0.25rem',
overflow: 'auto',
fontSize: '0.8rem',
color: '#d1d5db'
}}>
{error.name}: {error.message}
{error.stack && `\n\nStack Trace:\n${error.stack}`}
</pre>
</details>
</div>
</body>
</html>
)
Expand Down
Loading