fix(admin-v2): Restore complete admin-v2 application
The admin-v2 application was incomplete in the repository. This commit restores all missing components: - Admin pages (76 pages): dashboard, ai, compliance, dsgvo, education, infrastructure, communication, development, onboarding, rbac - SDK pages (45 pages): tom, dsfa, vvt, loeschfristen, einwilligungen, vendor-compliance, tom-generator, dsr, and more - Developer portal (25 pages): API docs, SDK guides, frameworks - All components, lib files, hooks, and types - Updated package.json with all dependencies The issue was caused by incomplete initial repository state - the full admin-v2 codebase existed in backend/admin-v2 and docs-src/admin-v2 but was never fully synced to the main admin-v2 directory. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Audit Sign-off API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
// Sign off an item
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ sessionId: string; requirementId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { sessionId, requirementId } = await params
|
||||
const body = await request.json()
|
||||
|
||||
const response = await fetch(
|
||||
`${BACKEND_URL}/api/v1/compliance/audit/checklist/${sessionId}/items/${requirementId}/sign-off`,
|
||||
{
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: AbortSignal.timeout(30000)
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Audit sign-off proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Get sign-off status
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ sessionId: string; requirementId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { sessionId, requirementId } = await params
|
||||
|
||||
const response = await fetch(
|
||||
`${BACKEND_URL}/api/v1/compliance/audit/checklist/${sessionId}/items/${requirementId}`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Get sign-off proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Audit Checklist API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ sessionId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { sessionId } = await params
|
||||
const { searchParams } = new URL(request.url)
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
const page = searchParams.get('page')
|
||||
const page_size = searchParams.get('page_size')
|
||||
const status_filter = searchParams.get('status_filter')
|
||||
const regulation_filter = searchParams.get('regulation_filter')
|
||||
const search = searchParams.get('search')
|
||||
|
||||
if (page) queryParams.set('page', page)
|
||||
if (page_size) queryParams.set('page_size', page_size)
|
||||
if (status_filter) queryParams.set('status_filter', status_filter)
|
||||
if (regulation_filter) queryParams.set('regulation_filter', regulation_filter)
|
||||
if (search) queryParams.set('search', search)
|
||||
|
||||
const url = `${BACKEND_URL}/api/v1/compliance/audit/checklist/${sessionId}${queryParams.toString() ? `?${queryParams}` : ''}`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Audit checklist proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Control Review API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ controlId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { controlId } = await params
|
||||
const body = await request.json()
|
||||
|
||||
const response = await fetch(
|
||||
`${BACKEND_URL}/api/v1/compliance/controls/${controlId}/review`,
|
||||
{
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: AbortSignal.timeout(30000)
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Control review proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
54
admin-v2/app/api/admin/compliance/controls/route.ts
Normal file
54
admin-v2/app/api/admin/compliance/controls/route.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Compliance Controls API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
// Forward query parameters
|
||||
const domain = searchParams.get('domain')
|
||||
const status = searchParams.get('status')
|
||||
const search = searchParams.get('search')
|
||||
const page = searchParams.get('page')
|
||||
const page_size = searchParams.get('page_size')
|
||||
|
||||
if (domain) queryParams.set('domain', domain)
|
||||
if (status) queryParams.set('status', status)
|
||||
if (search) queryParams.set('search', search)
|
||||
if (page) queryParams.set('page', page)
|
||||
if (page_size) queryParams.set('page_size', page_size)
|
||||
|
||||
const url = `${BACKEND_URL}/api/v1/compliance/controls${queryParams.toString() ? `?${queryParams}` : ''}`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Compliance controls proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen', controls: [] },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Compliance Executive Dashboard API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/dashboard/executive`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Executive dashboard proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
36
admin-v2/app/api/admin/compliance/dashboard/route.ts
Normal file
36
admin-v2/app/api/admin/compliance/dashboard/route.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Compliance Dashboard API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/dashboard`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Compliance dashboard proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
81
admin-v2/app/api/admin/compliance/evidence/route.ts
Normal file
81
admin-v2/app/api/admin/compliance/evidence/route.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Compliance Evidence API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
const control_id = searchParams.get('control_id')
|
||||
const evidence_type = searchParams.get('evidence_type')
|
||||
const status = searchParams.get('status')
|
||||
|
||||
if (control_id) queryParams.set('control_id', control_id)
|
||||
if (evidence_type) queryParams.set('evidence_type', evidence_type)
|
||||
if (status) queryParams.set('status', status)
|
||||
|
||||
const url = `${BACKEND_URL}/api/v1/compliance/evidence${queryParams.toString() ? `?${queryParams}` : ''}`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Compliance evidence proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen', evidence: [] },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/evidence`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Create evidence proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
53
admin-v2/app/api/admin/compliance/evidence/upload/route.ts
Normal file
53
admin-v2/app/api/admin/compliance/evidence/upload/route.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Evidence Upload API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
const control_id = searchParams.get('control_id')
|
||||
const evidence_type = searchParams.get('evidence_type')
|
||||
const title = searchParams.get('title')
|
||||
const description = searchParams.get('description')
|
||||
|
||||
if (control_id) queryParams.set('control_id', control_id)
|
||||
if (evidence_type) queryParams.set('evidence_type', evidence_type)
|
||||
if (title) queryParams.set('title', title)
|
||||
if (description) queryParams.set('description', description)
|
||||
|
||||
// Forward the FormData directly
|
||||
const formData = await request.formData()
|
||||
|
||||
const response = await fetch(
|
||||
`${BACKEND_URL}/api/v1/compliance/evidence/upload?${queryParams}`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
signal: AbortSignal.timeout(60000) // 60 seconds for file upload
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Evidence upload proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Compliance Module Detail API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ moduleId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { moduleId } = await params
|
||||
|
||||
const response = await fetch(
|
||||
`${BACKEND_URL}/api/v1/compliance/modules/${moduleId}`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Module detail proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
36
admin-v2/app/api/admin/compliance/modules/overview/route.ts
Normal file
36
admin-v2/app/api/admin/compliance/modules/overview/route.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Compliance Modules Overview API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/modules/overview`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Modules overview proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
51
admin-v2/app/api/admin/compliance/modules/route.ts
Normal file
51
admin-v2/app/api/admin/compliance/modules/route.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Compliance Modules API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
const service_type = searchParams.get('service_type')
|
||||
const criticality = searchParams.get('criticality')
|
||||
const processes_pii = searchParams.get('processes_pii')
|
||||
const ai_components = searchParams.get('ai_components')
|
||||
|
||||
if (service_type) queryParams.set('service_type', service_type)
|
||||
if (criticality) queryParams.set('criticality', criticality)
|
||||
if (processes_pii) queryParams.set('processes_pii', processes_pii)
|
||||
if (ai_components) queryParams.set('ai_components', ai_components)
|
||||
|
||||
const url = `${BACKEND_URL}/api/v1/compliance/modules${queryParams.toString() ? `?${queryParams}` : ''}`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Compliance modules proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen', modules: [] },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
39
admin-v2/app/api/admin/compliance/modules/seed/route.ts
Normal file
39
admin-v2/app/api/admin/compliance/modules/seed/route.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Compliance Modules Seed API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/modules/seed`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: AbortSignal.timeout(60000) // 60 seconds for seeding
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Modules seed proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
220
admin-v2/app/api/admin/compliance/regulations/route.ts
Normal file
220
admin-v2/app/api/admin/compliance/regulations/route.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* Compliance Regulations API Route - Proxy to Backend
|
||||
*
|
||||
* Returns all 21 regulations with source URLs to original documents
|
||||
* Includes: GDPR, ePrivacy, TDDDG, SCC, DPF, AI Act, CRA, NIS2, EU CSA,
|
||||
* Data Act, DGA, DSA, EAA, DSM, PLD, GPSR, BSI-TR-03161 (1-3), BSI C5, DORA
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/regulations`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
// If backend doesn't have this endpoint yet, return seed data
|
||||
if (response.status === 404) {
|
||||
return NextResponse.json({
|
||||
regulations: getStaticRegulations()
|
||||
})
|
||||
}
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Regulations proxy error:', error)
|
||||
// Return static data as fallback
|
||||
return NextResponse.json({
|
||||
regulations: getStaticRegulations()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Static seed data with source URLs - matches regulations.py
|
||||
function getStaticRegulations() {
|
||||
return [
|
||||
{
|
||||
id: '1', code: 'GDPR', name: 'DSGVO',
|
||||
full_name: 'Verordnung (EU) 2016/679 - Datenschutz-Grundverordnung',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2016/679/oj/eng',
|
||||
description: 'Grundverordnung zum Schutz natuerlicher Personen bei der Verarbeitung personenbezogener Daten.',
|
||||
is_active: true, requirement_count: 99,
|
||||
},
|
||||
{
|
||||
id: '2', code: 'EPRIVACY', name: 'ePrivacy-Richtlinie',
|
||||
full_name: 'Richtlinie 2002/58/EG',
|
||||
regulation_type: 'eu_directive',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/dir/2002/58/oj/eng',
|
||||
description: 'Datenschutz in der elektronischen Kommunikation, Cookies und Tracking.',
|
||||
is_active: true, requirement_count: 25,
|
||||
},
|
||||
{
|
||||
id: '3', code: 'TDDDG', name: 'TDDDG',
|
||||
full_name: 'Telekommunikation-Digitale-Dienste-Datenschutz-Gesetz',
|
||||
regulation_type: 'de_law',
|
||||
source_url: 'https://www.gesetze-im-internet.de/ttdsg/',
|
||||
description: 'Deutsche Umsetzung der ePrivacy-Richtlinie.',
|
||||
is_active: true, requirement_count: 15,
|
||||
},
|
||||
{
|
||||
id: '4', code: 'SCC', name: 'Standardvertragsklauseln',
|
||||
full_name: 'Durchfuehrungsbeschluss (EU) 2021/914',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/dec_impl/2021/914/oj/eng',
|
||||
description: 'Standardvertragsklauseln fuer Drittlandtransfers.',
|
||||
is_active: true, requirement_count: 18,
|
||||
},
|
||||
{
|
||||
id: '5', code: 'DPF', name: 'EU-US Data Privacy Framework',
|
||||
full_name: 'Durchfuehrungsbeschluss (EU) 2023/1795',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/dec_impl/2023/1795/oj',
|
||||
description: 'Angemessenheitsbeschluss fuer USA-Transfers.',
|
||||
is_active: true, requirement_count: 12,
|
||||
},
|
||||
{
|
||||
id: '6', code: 'AIACT', name: 'EU AI Act',
|
||||
full_name: 'Verordnung (EU) 2024/1689 - KI-Verordnung',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2024/1689/oj/eng',
|
||||
description: 'EU-Verordnung zur Regulierung von KI-Systemen nach Risikostufen.',
|
||||
is_active: true, requirement_count: 85,
|
||||
},
|
||||
{
|
||||
id: '7', code: 'CRA', name: 'Cyber Resilience Act',
|
||||
full_name: 'Verordnung (EU) 2024/2847',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2024/2847/oj/eng',
|
||||
description: 'Cybersicherheitsanforderungen, SBOM-Pflicht.',
|
||||
is_active: true, requirement_count: 45,
|
||||
},
|
||||
{
|
||||
id: '8', code: 'NIS2', name: 'NIS2-Richtlinie',
|
||||
full_name: 'Richtlinie (EU) 2022/2555',
|
||||
regulation_type: 'eu_directive',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/dir/2022/2555/oj/eng',
|
||||
description: 'Cybersicherheit fuer wesentliche Einrichtungen.',
|
||||
is_active: true, requirement_count: 46,
|
||||
},
|
||||
{
|
||||
id: '9', code: 'EUCSA', name: 'EU Cybersecurity Act',
|
||||
full_name: 'Verordnung (EU) 2019/881',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2019/881/oj/eng',
|
||||
description: 'ENISA und Cybersicherheitszertifizierung.',
|
||||
is_active: true, requirement_count: 35,
|
||||
},
|
||||
{
|
||||
id: '10', code: 'DATAACT', name: 'Data Act',
|
||||
full_name: 'Verordnung (EU) 2023/2854',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2023/2854/oj/eng',
|
||||
description: 'Fairer Datenzugang, IoT-Daten, Cloud-Wechsel.',
|
||||
is_active: true, requirement_count: 42,
|
||||
},
|
||||
{
|
||||
id: '11', code: 'DGA', name: 'Data Governance Act',
|
||||
full_name: 'Verordnung (EU) 2022/868',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2022/868/oj/eng',
|
||||
description: 'Weiterverwendung oeffentlicher Daten.',
|
||||
is_active: true, requirement_count: 35,
|
||||
},
|
||||
{
|
||||
id: '12', code: 'DSA', name: 'Digital Services Act',
|
||||
full_name: 'Verordnung (EU) 2022/2065',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2022/2065/oj/eng',
|
||||
description: 'Digitale Dienste, Transparenzpflichten.',
|
||||
is_active: true, requirement_count: 93,
|
||||
},
|
||||
{
|
||||
id: '13', code: 'EAA', name: 'European Accessibility Act',
|
||||
full_name: 'Richtlinie (EU) 2019/882',
|
||||
regulation_type: 'eu_directive',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/dir/2019/882/oj/eng',
|
||||
description: 'Barrierefreiheit digitaler Produkte.',
|
||||
is_active: true, requirement_count: 25,
|
||||
},
|
||||
{
|
||||
id: '14', code: 'DSM', name: 'DSM-Urheberrechtsrichtlinie',
|
||||
full_name: 'Richtlinie (EU) 2019/790',
|
||||
regulation_type: 'eu_directive',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/dir/2019/790/oj/eng',
|
||||
description: 'Urheberrecht, Text- und Data-Mining.',
|
||||
is_active: true, requirement_count: 22,
|
||||
},
|
||||
{
|
||||
id: '15', code: 'PLD', name: 'Produkthaftungsrichtlinie',
|
||||
full_name: 'Richtlinie (EU) 2024/2853',
|
||||
regulation_type: 'eu_directive',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/dir/2024/2853/oj/eng',
|
||||
description: 'Produkthaftung inkl. Software und KI.',
|
||||
is_active: true, requirement_count: 18,
|
||||
},
|
||||
{
|
||||
id: '16', code: 'GPSR', name: 'General Product Safety',
|
||||
full_name: 'Verordnung (EU) 2023/988',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2023/988/oj/eng',
|
||||
description: 'Allgemeine Produktsicherheit.',
|
||||
is_active: true, requirement_count: 30,
|
||||
},
|
||||
{
|
||||
id: '17', code: 'BSI-TR-03161-1', name: 'BSI-TR-03161 Teil 1',
|
||||
full_name: 'BSI Technische Richtlinie - Allgemeine Anforderungen',
|
||||
regulation_type: 'bsi_standard',
|
||||
source_url: 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-1.html',
|
||||
description: 'Allgemeine Sicherheitsanforderungen (45 Pruefaspekte).',
|
||||
is_active: true, requirement_count: 45,
|
||||
},
|
||||
{
|
||||
id: '18', code: 'BSI-TR-03161-2', name: 'BSI-TR-03161 Teil 2',
|
||||
full_name: 'BSI Technische Richtlinie - Web-Anwendungen',
|
||||
regulation_type: 'bsi_standard',
|
||||
source_url: 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-2.html',
|
||||
description: 'Web-Sicherheit (40 Pruefaspekte).',
|
||||
is_active: true, requirement_count: 40,
|
||||
},
|
||||
{
|
||||
id: '19', code: 'BSI-TR-03161-3', name: 'BSI-TR-03161 Teil 3',
|
||||
full_name: 'BSI Technische Richtlinie - Hintergrundsysteme',
|
||||
regulation_type: 'bsi_standard',
|
||||
source_url: 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/TechnischeRichtlinien/TR03161/BSI-TR-03161-3.html',
|
||||
description: 'Backend-Sicherheit (35 Pruefaspekte).',
|
||||
is_active: true, requirement_count: 35,
|
||||
},
|
||||
{
|
||||
id: '20', code: 'BSI-C5', name: 'BSI C5',
|
||||
full_name: 'Cloud Computing Compliance Criteria Catalogue',
|
||||
regulation_type: 'bsi_standard',
|
||||
source_url: 'https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Informationen-und-Empfehlungen/Empfehlungen-nach-Angriffszielen/Cloud-Computing/Kriterienkatalog-C5/kriterienkatalog-c5_node.html',
|
||||
description: 'Deutscher Cloud-Sicherheitsstandard mit 121 Kriterien in 17 Bereichen (OIS, SP, HR, AM, PS, OPS, COS, IDM, CRY, SIM, BCM, COM, SA, SUA, PI).',
|
||||
is_active: true, requirement_count: 121,
|
||||
},
|
||||
{
|
||||
id: '21', code: 'DORA', name: 'DORA',
|
||||
full_name: 'Verordnung (EU) 2022/2554 - Digital Operational Resilience Act',
|
||||
regulation_type: 'eu_regulation',
|
||||
source_url: 'https://eur-lex.europa.eu/eli/reg/2022/2554/oj/deu',
|
||||
description: 'EU-Verordnung fuer digitale operationale Resilienz im Finanzsektor. IKT-Risikomanagement, Incident-Reporting, Resilienztests, Drittparteienrisiko.',
|
||||
is_active: true, requirement_count: 64,
|
||||
},
|
||||
]
|
||||
}
|
||||
109
admin-v2/app/api/admin/compliance/requirements/route.ts
Normal file
109
admin-v2/app/api/admin/compliance/requirements/route.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Compliance Requirements API Route - Proxy to Backend
|
||||
*
|
||||
* Returns requirements for a specific regulation with implementation status
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const searchParams = request.nextUrl.searchParams
|
||||
const regulationCode = searchParams.get('regulation_code')
|
||||
|
||||
if (!regulationCode) {
|
||||
return NextResponse.json(
|
||||
{ error: 'regulation_code parameter required' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// Build query string for backend
|
||||
const params = new URLSearchParams()
|
||||
params.set('regulation_code', regulationCode)
|
||||
if (searchParams.get('status')) params.set('status', searchParams.get('status')!)
|
||||
if (searchParams.get('priority')) params.set('priority', searchParams.get('priority')!)
|
||||
if (searchParams.get('search')) params.set('search', searchParams.get('search')!)
|
||||
|
||||
const response = await fetch(
|
||||
`${BACKEND_URL}/api/v1/compliance/requirements?${params}`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
signal: AbortSignal.timeout(30000)
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
// Return static BSI data as fallback if backend not available
|
||||
if (response.status === 404 && regulationCode.startsWith('BSI')) {
|
||||
return NextResponse.json({
|
||||
requirements: getBSIRequirements(regulationCode)
|
||||
})
|
||||
}
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Requirements proxy error:', error)
|
||||
// Return fallback data for BSI
|
||||
const regulationCode = request.nextUrl.searchParams.get('regulation_code')
|
||||
if (regulationCode?.startsWith('BSI')) {
|
||||
return NextResponse.json({
|
||||
requirements: getBSIRequirements(regulationCode)
|
||||
})
|
||||
}
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen', requirements: [] },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Static BSI requirements as fallback (subset)
|
||||
function getBSIRequirements(code: string) {
|
||||
if (code === 'BSI-TR-03161-1') {
|
||||
return [
|
||||
{ id: '1', regulation_code: code, article: 'O.Purp_1', title: 'Zweckbindung', description: 'Anwendungszweck klar definiert', implementation_status: 'implemented', priority: 1, controls_count: 2 },
|
||||
{ id: '2', regulation_code: code, article: 'O.Data_1', title: 'Datenminimierung', description: 'Nur notwendige Daten erheben', implementation_status: 'implemented', priority: 1, controls_count: 3 },
|
||||
{ id: '3', regulation_code: code, article: 'O.Auth_1', title: 'Authentifizierung', description: 'Sichere Authentifizierungsmechanismen', implementation_status: 'verified', priority: 1, controls_count: 4 },
|
||||
{ id: '4', regulation_code: code, article: 'O.Auth_2', title: 'Passwortrichtlinie', description: 'Starke Passwoerter erzwingen', implementation_status: 'implemented', priority: 1, controls_count: 2 },
|
||||
{ id: '5', regulation_code: code, article: 'O.Cryp_1', title: 'TLS-Verschluesselung', description: 'TLS 1.2+ fuer Transport', implementation_status: 'verified', priority: 1, controls_count: 2 },
|
||||
{ id: '6', regulation_code: code, article: 'O.Cryp_2', title: 'Encryption at Rest', description: 'Sensible Daten verschluesseln', implementation_status: 'implemented', priority: 1, controls_count: 2 },
|
||||
{ id: '7', regulation_code: code, article: 'O.Priv_1', title: 'Datenschutzerklaerung', description: 'Transparente Information', implementation_status: 'verified', priority: 1, controls_count: 1 },
|
||||
{ id: '8', regulation_code: code, article: 'O.Log_1', title: 'Security Logging', description: 'Sicherheitsereignisse protokollieren', implementation_status: 'in_progress', priority: 1, controls_count: 2 },
|
||||
]
|
||||
}
|
||||
if (code === 'BSI-TR-03161-2') {
|
||||
return [
|
||||
{ id: '20', regulation_code: code, article: 'O.Sess_1', title: 'Session-Timeout', description: 'Automatische Sitzungsbeendigung', implementation_status: 'implemented', priority: 1, controls_count: 2 },
|
||||
{ id: '21', regulation_code: code, article: 'O.Input_1', title: 'Eingabevalidierung', description: 'Alle Eingaben validieren', implementation_status: 'verified', priority: 1, controls_count: 3 },
|
||||
{ id: '22', regulation_code: code, article: 'O.SQL_1', title: 'SQL-Injection Schutz', description: 'Prepared Statements', implementation_status: 'verified', priority: 1, controls_count: 2 },
|
||||
{ id: '23', regulation_code: code, article: 'O.XSS_1', title: 'XSS-Schutz', description: 'Output Encoding', implementation_status: 'verified', priority: 1, controls_count: 3 },
|
||||
{ id: '24', regulation_code: code, article: 'O.CSRF_1', title: 'CSRF-Schutz', description: 'Anti-CSRF Token', implementation_status: 'implemented', priority: 1, controls_count: 2 },
|
||||
{ id: '25', regulation_code: code, article: 'O.Head_1', title: 'Security Headers', description: 'X-Content-Type-Options', implementation_status: 'verified', priority: 1, controls_count: 1 },
|
||||
{ id: '26', regulation_code: code, article: 'O.API_1', title: 'API-Authentifizierung', description: 'JWT/OAuth', implementation_status: 'verified', priority: 1, controls_count: 2 },
|
||||
{ id: '27', regulation_code: code, article: 'O.API_2', title: 'Rate Limiting', description: 'Anfragen begrenzen', implementation_status: 'implemented', priority: 1, controls_count: 1 },
|
||||
]
|
||||
}
|
||||
if (code === 'BSI-TR-03161-3') {
|
||||
return [
|
||||
{ id: '40', regulation_code: code, article: 'O.Arch_1', title: 'Defense in Depth', description: 'Mehrschichtige Sicherheit', implementation_status: 'implemented', priority: 1, controls_count: 3 },
|
||||
{ id: '41', regulation_code: code, article: 'O.DB_1', title: 'Datenbank-Sicherheit', description: 'DB abhaerten', implementation_status: 'implemented', priority: 1, controls_count: 2 },
|
||||
{ id: '42', regulation_code: code, article: 'O.Cont_1', title: 'Container-Sicherheit', description: 'Images scannen', implementation_status: 'in_progress', priority: 1, controls_count: 2 },
|
||||
{ id: '43', regulation_code: code, article: 'O.Sec_1', title: 'Secrets Management', description: 'Zentrale Secrets-Verwaltung', implementation_status: 'verified', priority: 1, controls_count: 2 },
|
||||
{ id: '44', regulation_code: code, article: 'O.Mon_1', title: 'Zentrale Logs', description: 'Log-Aggregation', implementation_status: 'implemented', priority: 1, controls_count: 1 },
|
||||
{ id: '45', regulation_code: code, article: 'O.CI_1', title: 'Pipeline-Sicherheit', description: 'CI/CD absichern', implementation_status: 'in_progress', priority: 1, controls_count: 2 },
|
||||
{ id: '46', regulation_code: code, article: 'O.DR_1', title: 'Backup-Strategie', description: '3-2-1 Backup-Regel', implementation_status: 'implemented', priority: 1, controls_count: 1 },
|
||||
]
|
||||
}
|
||||
return []
|
||||
}
|
||||
83
admin-v2/app/api/admin/compliance/risks/[riskId]/route.ts
Normal file
83
admin-v2/app/api/admin/compliance/risks/[riskId]/route.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Risk Update API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ riskId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { riskId } = await params
|
||||
const body = await request.json()
|
||||
|
||||
const response = await fetch(
|
||||
`${BACKEND_URL}/api/v1/compliance/risks/${riskId}`,
|
||||
{
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: AbortSignal.timeout(30000)
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Risk update proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ riskId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { riskId } = await params
|
||||
|
||||
const response = await fetch(
|
||||
`${BACKEND_URL}/api/v1/compliance/risks/${riskId}`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Get risk proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
81
admin-v2/app/api/admin/compliance/risks/route.ts
Normal file
81
admin-v2/app/api/admin/compliance/risks/route.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Compliance Risks API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
const level = searchParams.get('level')
|
||||
const status = searchParams.get('status')
|
||||
const category = searchParams.get('category')
|
||||
|
||||
if (level) queryParams.set('level', level)
|
||||
if (status) queryParams.set('status', status)
|
||||
if (category) queryParams.set('category', category)
|
||||
|
||||
const url = `${BACKEND_URL}/api/v1/compliance/risks${queryParams.toString() ? `?${queryParams}` : ''}`
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Compliance risks proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen', risks: [] },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/risks`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: AbortSignal.timeout(30000)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Create risk proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
39
admin-v2/app/api/admin/compliance/seed/route.ts
Normal file
39
admin-v2/app/api/admin/compliance/seed/route.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Compliance Seed API Route - Proxy to Backend
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/compliance/seed`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: AbortSignal.timeout(60000) // 60s timeout for seeding
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return NextResponse.json(
|
||||
{ error: `Backend Error: ${response.status}`, details: errorText },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
console.error('Compliance seed proxy error:', error)
|
||||
return NextResponse.json(
|
||||
{ error: 'Verbindung zum Backend fehlgeschlagen' },
|
||||
{ status: 503 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user