feat: implement admin validation middleware, DB integrity scan, automatic schema repair, and reindexing dashboard

This commit is contained in:
DanielS
2026-06-24 13:06:23 +02:00
parent 6e5cee0180
commit 3c60889e2a
5 changed files with 565 additions and 0 deletions

49
shop/lib/actions/admin.ts Normal file
View File

@@ -0,0 +1,49 @@
'use server'
import { createClient } from '@/lib/supabase/server'
import { verifyAdmin } from '@/lib/actions/auth'
export async function getDatabaseIntegrity() {
try {
await verifyAdmin()
const supabase = await createClient()
const { data, error } = await supabase.rpc('check_database_integrity')
if (error) {
return { success: false, error: error.message }
}
return { success: true, data }
} catch (err: any) {
console.error("Error in getDatabaseIntegrity:", err)
return { success: false, error: err.message || "Unerwarteter Fehler beim Integritätsscan." }
}
}
export async function repairDatabaseSchema() {
try {
await verifyAdmin()
const supabase = await createClient()
const { data, error } = await supabase.rpc('repair_database_schema')
if (error) {
return { success: false, error: error.message }
}
return { success: true, data }
} catch (err: any) {
console.error("Error in repairDatabaseSchema:", err)
return { success: false, error: err.message || "Unerwarteter Fehler bei der Schemareparatur." }
}
}
export async function optimizeDatabaseIndices() {
try {
await verifyAdmin()
const supabase = await createClient()
const { data, error } = await supabase.rpc('optimize_database_indices')
if (error) {
return { success: false, error: error.message }
}
return { success: true, data }
} catch (err: any) {
console.error("Error in optimizeDatabaseIndices:", err)
return { success: false, error: err.message || "Unerwarteter Fehler bei der Indexoptimierung." }
}
}

View File

@@ -98,3 +98,20 @@ export async function updatePassword(password: string) {
}
return { success: true }
}
export async function verifyAdmin() {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) throw new Error("Nicht authentifiziert.")
const { data: userData, error } = await supabase
.from('users')
.select('role')
.eq('id', user.id)
.single()
if (error || !userData || userData.role !== 'admin') {
throw new Error("Zugriff verweigert. Nur Administratoren erlaubt.")
}
return user
}

View File

@@ -63,6 +63,27 @@ export async function updateSession(request: NextRequest) {
return NextResponse.redirect(url);
}
// Admin protection
if (request.nextUrl.pathname.startsWith("/admin")) {
if (!user || !user.sub) {
const url = request.nextUrl.clone();
url.pathname = "/auth/login";
return NextResponse.redirect(url);
}
const { data: dbUser } = await supabase
.from("users")
.select("role")
.eq("id", user.sub)
.single();
if (!dbUser || dbUser.role !== "admin") {
const url = request.nextUrl.clone();
url.pathname = "/";
return NextResponse.redirect(url);
}
}
// IMPORTANT: You *must* return the supabaseResponse object as it is.
// If you're creating a new response object with NextResponse.next() make sure to:
// 1. Pass the request in it, like so: