security: fix 6 critical RLS vulns, SHA-256 hash, DSGVO [GELÖSCHT], completed status
Some checks failed
Staging Build / build (push) Has been cancelled
Some checks failed
Staging Build / build (push) Has been cancelled
This commit is contained in:
@@ -167,17 +167,17 @@ export async function anonymizeEndCustomer(id: string): Promise<void> {
|
||||
.from('end_customers')
|
||||
.update({
|
||||
company_name: '[GELÖSCHT]',
|
||||
vat_id: null,
|
||||
vat_id: '[GELÖSCHT]',
|
||||
first_name: '[GELÖSCHT]',
|
||||
last_name: '[GELÖSCHT]',
|
||||
street: '[GELÖSCHT]',
|
||||
zip: null,
|
||||
city: null,
|
||||
email: null,
|
||||
bank_iban: null,
|
||||
bank_bic: null,
|
||||
bank_name: null,
|
||||
bank_owner: null,
|
||||
zip: '[GELÖSCHT]',
|
||||
city: '[GELÖSCHT]',
|
||||
email: '[GELÖSCHT]',
|
||||
bank_iban: '[GELÖSCHT]',
|
||||
bank_bic: '[GELÖSCHT]',
|
||||
bank_name: '[GELÖSCHT]',
|
||||
bank_owner: '[GELÖSCHT]',
|
||||
is_anonymized: true,
|
||||
})
|
||||
.eq('id', id)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use server'
|
||||
|
||||
import { createClient } from '@/lib/supabase/server'
|
||||
import { createHash } from 'crypto'
|
||||
import { createAdminClient } from '@/lib/supabase/admin'
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import { sendMail } from '@/utils/mail'
|
||||
@@ -25,18 +26,12 @@ function generateOrderNumber(): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt einen einfachen deterministischen Hash aus dem Bestell-Snapshot.
|
||||
* Erstellt einen SHA-256 Hash aus dem Bestell-Snapshot.
|
||||
* Wird für den Idempotenz-Guard verwendet (verhindert Doppelbestellungen).
|
||||
*/
|
||||
function hashOrderSnapshot(snapshot: object): string {
|
||||
const str = JSON.stringify(snapshot)
|
||||
let hash = 0
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const char = str.charCodeAt(i)
|
||||
hash = ((hash << 5) - hash) + char
|
||||
hash = hash & hash // 32-bit integer
|
||||
}
|
||||
return Math.abs(hash).toString(36)
|
||||
return createHash('sha256').update(str).digest('hex')
|
||||
}
|
||||
|
||||
// ─── submitOrder ──────────────────────────────────────────────────────────────
|
||||
@@ -155,16 +150,16 @@ export async function submitOrder(params: {
|
||||
const customerSnapshot = buildCustomerSnapshot(customerProfile, endCustomer ?? null)
|
||||
const orderSnapshot = buildOrderSnapshot(selections, dbProducts, dbCategories, billingInterval, moduleQuantities, lastLicenseDate)
|
||||
|
||||
// 2. Idempotenz-Guard: Prüfen ob identische Bestellung in den letzten 30s existiert
|
||||
// 2. Idempotenz-Guard: Prüfen ob identische Bestellung in den letzten 5 Minuten existiert
|
||||
const orderHash = hashOrderSnapshot(orderSnapshot)
|
||||
const thirtySecondsAgo = new Date(Date.now() - 30_000).toISOString()
|
||||
const fiveMinutesAgo = new Date(Date.now() - 5 * 60_000).toISOString()
|
||||
|
||||
const { data: existingOrder } = await supabase
|
||||
.from('orders')
|
||||
.select('*')
|
||||
.eq('user_id', user.id)
|
||||
.eq('order_hash', orderHash)
|
||||
.gte('created_at', thirtySecondsAgo)
|
||||
.gte('created_at', fiveMinutesAgo)
|
||||
.maybeSingle()
|
||||
|
||||
if (existingOrder) {
|
||||
|
||||
Reference in New Issue
Block a user