Skip to content
Merged
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
13 changes: 12 additions & 1 deletion app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ import {
ArrowDownRight,
ClipboardCheck,
Zap,
Webhook,
} from "lucide-react"
import { createClient } from "@/lib/supabase/client"
import type { BlogPost } from "@/components/data/blog-posts"
import { RealtimeChannel } from "@supabase/supabase-js"
import { CacheAnalyticsDashboard } from "@/components/admin/CacheAnalyticsSimple"
// import { CacheManagementDashboard } from "@/components/admin/CacheManagementDashboard"
import { WebhookManagementDashboard } from "@/components/admin/WebhookManagementDashboard"
import PerformanceMonitoring from "@/components/admin/PerformanceMonitoring"
import SecurityMonitoring from "@/components/admin/SecurityMonitoring"

Expand Down Expand Up @@ -550,7 +553,7 @@ export default function AdminDashboard() {

<div className="relative z-10">
<Tabs defaultValue="cache" className="w-full">
<TabsList className="grid w-full grid-cols-3 bg-zinc-900/60 border border-zinc-800">
<TabsList className="grid w-full grid-cols-4 bg-zinc-900/60 border border-zinc-800">
<TabsTrigger value="cache" className="data-[state=active]:bg-blue-600 data-[state=active]:text-white">
<Zap className="w-4 h-4 mr-2" />
Cache Analytics
Expand All @@ -563,6 +566,10 @@ export default function AdminDashboard() {
<AlertTriangle className="w-4 h-4 mr-2" />
Security
</TabsTrigger>
<TabsTrigger value="webhooks" className="data-[state=active]:bg-purple-600 data-[state=active]:text-white">
<Webhook className="w-4 h-4 mr-2" />
Webhooks
</TabsTrigger>
</TabsList>

<TabsContent value="cache" className="mt-6">
Expand All @@ -576,6 +583,10 @@ export default function AdminDashboard() {
<TabsContent value="security" className="mt-6">
<SecurityMonitoring />
</TabsContent>

<TabsContent value="webhooks" className="mt-6">
<WebhookManagementDashboard />
</TabsContent>
</Tabs>
</div>

Expand Down
14 changes: 7 additions & 7 deletions app/api/admin/cache-analytics/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NextRequest } from 'next/server'
import { createCachedResponse } from '@/lib/simple-cache'
import { UnifiedCache } from '@/lib/unified-cache-system'

/**
* API endpoint for cache analytics - Admin only
Expand All @@ -16,11 +16,11 @@ export async function GET(request: NextRequest) {
// }

const url = new URL(request.url)
const period = url.searchParams.get('period')
// const period = url.searchParams.get('period')
const format = url.searchParams.get('format') as 'json' | 'csv' | null

// Default to 24 hours
const periodMs = period ? parseInt(period) * 1000 : 24 * 60 * 60 * 1000
// Default to 24 hours - period is used for future analytics filtering
// const _periodMs = period ? parseInt(period) * 1000 : 24 * 60 * 60 * 1000

// Provide basic analytics data for now
const basicAnalytics = {
Expand Down Expand Up @@ -66,12 +66,12 @@ export async function GET(request: NextRequest) {
})
}

return createCachedResponse(basicAnalytics, 'API_SHORT')
return UnifiedCache.createResponse(basicAnalytics, 'API_STANDARD')
} catch (error) {
console.error('Cache analytics API error:', error)
return createCachedResponse(
return UnifiedCache.createResponse(
{ error: 'Failed to fetch cache analytics' },
'NO_CACHE'
'USER_PRIVATE'
)
}
}
6 changes: 3 additions & 3 deletions app/api/admin/cache-invalidate/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NextRequest } from 'next/server'
import { cacheAnalytics } from '@/lib/cache-analytics-server'
import { createCachedApiResponse } from '@/lib/production-cache'
import { UnifiedCache } from '@/lib/unified-cache-system'

/**
* API endpoint to trigger manual cache invalidation - Admin only
Expand All @@ -27,15 +27,15 @@ export async function POST(request: NextRequest) {
// Here you could add additional invalidation logic
// For example, clearing specific cache keys or triggering CDN purge

return createCachedApiResponse({
return UnifiedCache.createResponse({
success: true,
message: 'Cache invalidation triggered',
timestamp: new Date().toISOString()
}, 'USER_PRIVATE')

} catch (error) {
console.error('Cache invalidation API error:', error)
return createCachedApiResponse(
return UnifiedCache.createResponse(
{ error: 'Failed to trigger cache invalidation' },
'USER_PRIVATE'
)
Expand Down
67 changes: 67 additions & 0 deletions app/api/admin/cache-management/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Cache Management API
*
* Provides endpoints for:
* - Manual cache purging
* - Cache status monitoring
* - Webhook handling for automatic purges
*/

import { NextRequest } from 'next/server'
import { handleCachePurgeWebhook, CacheManager } from '@/lib/cloudflare-cache-purge'
import { UnifiedCache } from '@/lib/unified-cache-system'

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function GET(_request: NextRequest) {
try {
// TODO: Add admin authentication
// const user = await getUser(_request)
// if (!user?.isAdmin) {
// return new Response('Unauthorized', { status: 401 })
// }

const status = await CacheManager.getStatus()

return UnifiedCache.createResponse(status, 'USER_PRIVATE')
} catch (error) {
console.error('Cache status error:', error)
return UnifiedCache.createResponse(
{ error: 'Failed to get cache status' },
'USER_PRIVATE'
)
}
}

export async function POST(request: NextRequest) {
try {
// TODO: Add admin authentication
// const user = await getUser(request)
// if (!user?.isAdmin) {
// return new Response('Unauthorized', { status: 401 })
// }

const { action, type } = await request.json()

if (action === 'purge') {
const result = await CacheManager.manualPurge(type)
return UnifiedCache.createResponse(result, 'USER_PRIVATE')
}

if (action === 'webhook') {
const { webhookAction, data } = await request.json()
const result = await handleCachePurgeWebhook(webhookAction, data)
return UnifiedCache.createResponse(result, 'USER_PRIVATE')
}

return UnifiedCache.createResponse(
{ success: false, message: 'Invalid action' },
'USER_PRIVATE'
)
} catch (error) {
console.error('Cache management error:', error)
return UnifiedCache.createResponse(
{ error: 'Cache management failed' },
'USER_PRIVATE'
)
}
}
8 changes: 4 additions & 4 deletions app/api/admin/cache-test-data/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NextRequest } from 'next/server'
import { cacheAnalytics } from '@/lib/cache-analytics-server'
import { createCachedApiResponse } from '@/lib/production-cache'
import { UnifiedCache } from '@/lib/unified-cache-system'

const routes = [
'/api/hackathons',
Expand Down Expand Up @@ -79,15 +79,15 @@ export async function POST(request: NextRequest) {
// Return current analytics data
const analytics = cacheAnalytics.getDetailedAnalytics()

return createCachedApiResponse({
return UnifiedCache.createResponse({
success: true,
message: `Generated ${totalGenerated} cache events`,
analytics
}, 'API_REALTIME')
}, 'REALTIME')

} catch (error) {
console.error('Error generating cache test data:', error)
return createCachedApiResponse(
return UnifiedCache.createResponse(
{
success: false,
error: 'Failed to generate cache test data',
Expand Down
65 changes: 65 additions & 0 deletions app/api/hackathons/enhanced/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* Enhanced Hackathons API with Production Caching
*/

import { NextRequest } from 'next/server'
import { UnifiedCache } from '@/lib/unified-cache-system'
import { createClient } from '@/lib/supabase/server'

export async function GET(request: NextRequest) {
try {
const url = new URL(request.url)
const featured = url.searchParams.get('featured') === 'true'
const limit = parseInt(url.searchParams.get('limit') || '10')

// Create cache key based on parameters
const cacheKey = `hackathons:${featured ? 'featured' : 'all'}:${limit}`

// Use cached query with 5-minute TTL
const hackathons = await UnifiedCache.cachedQuery(
cacheKey,
async () => {
const supabase = await createClient()

let query = supabase
.from('hackathons')
.select('*')
.order('created_at', { ascending: false })
.limit(limit)

if (featured) {
query = query.eq('featured', true)
}

const { data, error } = await query

if (error) {
throw new Error(`Database error: ${error.message}`)
}

return data || []
},
'DATABASE_QUERIES'
)

return UnifiedCache.createResponse(
{
hackathons,
count: hackathons.length,
featured,
timestamp: new Date().toISOString(),
},
'DYNAMIC_CONTENT'
)
} catch (error) {
console.error('Hackathons API error:', error)
return UnifiedCache.createResponse(
{
error: 'Failed to fetch hackathons',
hackathons: [],
count: 0,
},
'USER_PRIVATE'
)
}
}
Loading