Feat: Implement Audit Logging and integrate into Reservation actions

This commit is contained in:
2025-12-03 22:32:34 +03:00
parent eb4fedef2a
commit 9538107a13
4 changed files with 115 additions and 24 deletions

View File

@@ -3,6 +3,8 @@
import { createClient } from "@/lib/supabase/server"
import { revalidatePath } from "next/cache"
import { logAction } from "@/lib/logger"
export async function addPayment(reservationId: string, formData: FormData) {
const supabase = await createClient()
@@ -10,17 +12,23 @@ export async function addPayment(reservationId: string, formData: FormData) {
const type = formData.get('type')
const method = formData.get('method')
const { error } = await supabase.from('payments').insert({
const { data, error } = await supabase.from('payments').insert({
reservation_id: reservationId,
amount: amount,
payment_type: type,
payment_method: method,
status: 'paid', // Assuming immediate payment for now
paid_at: new Date().toISOString(),
})
}).select().single()
if (error) throw new Error(error.message)
await logAction('add_payment', 'payment', data.id, {
reservation_id: reservationId,
amount,
type
})
revalidatePath(`/dashboard/reservations/${reservationId}`)
}
@@ -34,6 +42,8 @@ export async function updateStatus(id: string, status: string) {
if (error) throw new Error(error.message)
await logAction('update_reservation_status', 'reservation', id, { status })
revalidatePath(`/dashboard/reservations/${id}`)
revalidatePath('/dashboard/reservations')
}

View File

@@ -14,6 +14,35 @@ export async function createReservation(data: {
}) {
const supabase = await createClient()
// 1. Check for conflicts
// We look for any reservation in the same hall that overlaps with the requested time range
const { data: conflicts, error: conflictError } = await supabase
.from('reservations')
.select('id')
.eq('hall_id', data.hall_id)
.neq('status', 'cancelled') // Ignore cancelled bookings
.or(`and(start_time.lte.${data.end_time},end_time.gte.${data.start_time})`)
if (conflictError) {
throw new Error("Müsaitlik kontrolü yapılırken hata oluştu: " + conflictError.message)
}
'use server'
import { createClient } from "@/lib/supabase/server"
import { revalidatePath } from "next/cache"
import { redirect } from "next/navigation"
import { logAction } from "@/lib/logger"
export async function createReservation(data: {
hall_id: string
customer_id: string
package_id?: string
start_time: string
end_time: string
notes?: string
}) {
const supabase = await createClient()
// 1. Check for conflicts
// We look for any reservation in the same hall that overlaps with the requested time range
const { data: conflicts, error: conflictError } = await supabase
@@ -32,7 +61,7 @@ export async function createReservation(data: {
}
// 2. Create Reservation
const { error } = await supabase.from('reservations').insert({
const { data: newReservation, error } = await supabase.from('reservations').insert({
hall_id: data.hall_id,
customer_id: data.customer_id,
package_id: data.package_id || null,
@@ -40,13 +69,19 @@ export async function createReservation(data: {
end_time: data.end_time,
status: 'pending', // Default to pending, admin must confirm
notes: data.notes,
})
}).select().single()
if (error) {
return { error: error.message }
}
await logAction('create_reservation', 'reservation', newReservation.id, {
hall_id: data.hall_id,
customer_id: data.customer_id,
start_time: data.start_time
})
revalidatePath('/dashboard/reservations')
revalidatePath('/dashboard/calendar')
redirect('/dashboard/reservations')
}
}

21
src/lib/logger.ts Normal file
View File

@@ -0,0 +1,21 @@
import { createClient } from "@/lib/supabase/server"
export async function logAction(
action: string,
entityType: string,
entityId: string,
details?: any
) {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) return
await supabase.from('audit_logs').insert({
user_id: user.id,
action,
entity_type: entityType,
entity_id: entityId,
details,
})
}

View File

@@ -95,3 +95,28 @@ $$ language plpgsql security definer;
create trigger on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();
-- Create Audit Logs Table
create table audit_logs (
id uuid default uuid_generate_v4() primary key,
user_id uuid references auth.users(id),
action text not null,
entity_type text not null,
entity_id uuid,
details jsonb,
created_at timestamp with time zone default timezone('utc'::text, now()) not null
);
-- RLS for Audit Logs
alter table audit_logs enable row level security;
create policy "Admins can read all logs" on audit_logs
for select using (
exists (
select 1 from profiles
where profiles.id = auth.uid() and profiles.role = 'admin'
)
);
create policy "Users can insert logs" on audit_logs
for insert with check (auth.uid() = user_id);