38980-vm/app-9w9pd00g5j41/TRIP_CREATE_SECURITY_TESTS.md
2026-03-04 18:25:09 +00:00

8.5 KiB
Raw Permalink Blame History

Trip Create Security Tests

Güvenlik Özellikleri

1. Zorunlu Kimlik Doğrulama (Auth Mandatory)

Özellik: Anonim kullanıcılar seyahat oluşturamaz.

Test Senaryoları:

// ❌ BAŞARISIZ: Giriş yapmadan seyahat oluşturma
await supabase.auth.signOut();
const result = await tripsApiSafe.create({
  title: "Test Seyahati"
});
// Beklenen: Error: "Seyahat oluşturmak için giriş yapmalısınız."

// ✅ BAŞARILI: Giriş yaparak seyahat oluşturma
await supabase.auth.signInWithPassword({
  email: "test@example.com",
  password: "password123"
});
const result = await tripsApiSafe.create({
  title: "Test Seyahati"
});
// Beklenen: Trip objesi döner

2. Rate Limiting (5 trip/saat)

Özellik: Kullanıcı saatte en fazla 5 seyahat oluşturabilir.

Test Senaryoları:

// ✅ İlk 5 seyahat başarılı
for (let i = 1; i <= 5; i++) {
  const result = await tripsApiSafe.create({
    title: `Seyahat ${i}`
  });
  console.log(`✅ Seyahat ${i} oluşturuldu`);
}

// ❌ 6. seyahat başarısız
try {
  await tripsApiSafe.create({
    title: "Seyahat 6"
  });
} catch (error) {
  console.log(error.message);
  // Beklenen: "Saatlik limit aşıldı. X dakika sonra tekrar deneyin."
}

// ⏰ 1 saat sonra tekrar dene
setTimeout(async () => {
  const result = await tripsApiSafe.create({
    title: "Yeni Seyahat"
  });
  console.log("✅ Limit sıfırlandı, yeni seyahat oluşturuldu");
}, 3600000);

3. Input Validation

Özellik: Tüm girişler doğrulanır ve sanitize edilir.

3.1 Başlık Validasyonu

// ❌ Başlık çok kısa (min: 3 karakter)
await tripsApiSafe.create({ title: "AB" });
// Beklenen: Error: "Seyahat başlığı en az 3 karakter olmalıdır."

// ❌ Başlık çok uzun (max: 200 karakter)
await tripsApiSafe.create({ 
  title: "A".repeat(201) 
});
// Beklenen: Error: "Seyahat başlığı en fazla 200 karakter olabilir."

// ❌ Başlık boş
await tripsApiSafe.create({ title: "" });
// Beklenen: Error: "Seyahat başlığı alanı zorunludur."

// ✅ Geçerli başlık
await tripsApiSafe.create({ 
  title: "İstanbul Gezisi" 
});

3.2 Açıklama Validasyonu

// ❌ Açıklama çok uzun (max: 2000 karakter)
await tripsApiSafe.create({
  title: "Test",
  description: "A".repeat(2001)
});
// Beklenen: Error: "Açıklama en fazla 2000 karakter olabilir."

// ✅ Geçerli açıklama
await tripsApiSafe.create({
  title: "Test",
  description: "Harika bir seyahat planı"
});

3.3 Tarih Validasyonu

// ❌ Bitiş tarihi başlangıçtan önce
await tripsApiSafe.create({
  title: "Test",
  start_date: "2026-03-01",
  end_date: "2026-02-01"
});
// Beklenen: Error: "Bitiş tarihi başlangıç tarihinden önce olamaz."

// ❌ Geçersiz tarih formatı
await tripsApiSafe.create({
  title: "Test",
  start_date: "invalid-date"
});
// Beklenen: Error: "Başlangıç tarihi geçersiz."

// ❌ Çok uzun seyahat (max: 365 gün)
await tripsApiSafe.create({
  title: "Test",
  start_date: "2026-01-01",
  end_date: "2027-02-01"
});
// Beklenen: Error: "Seyahat süresi en fazla 365 gün olabilir."

// ✅ Geçerli tarihler
await tripsApiSafe.create({
  title: "Test",
  start_date: "2026-03-01",
  end_date: "2026-03-10"
});

3.4 Konum Validasyonu

// ❌ Geçersiz enlem (lat: -90 ile 90 arası)
await tripsApiSafe.create({
  title: "Test",
  start_lat: 100,
  start_lng: 30
});
// Beklenen: Error: "Enlem değeri -90 ile 90 arasında olmalıdır."

// ❌ Geçersiz boylam (lng: -180 ile 180 arası)
await tripsApiSafe.create({
  title: "Test",
  start_lat: 40,
  start_lng: 200
});
// Beklenen: Error: "Boylam değeri -180 ile 180 arasında olmalıdır."

// ❌ Konum tipi sayı değil
await tripsApiSafe.create({
  title: "Test",
  start_lat: "invalid",
  start_lng: 30
});
// Beklenen: Error: "Konum bilgileri geçersiz."

// ✅ Geçerli konum
await tripsApiSafe.create({
  title: "Test",
  start_lat: 41.0082,
  start_lng: 28.9784
});

3.5 İlgi Alanları Validasyonu

// ❌ Çok fazla ilgi alanı (max: 20)
await tripsApiSafe.create({
  title: "Test",
  interests: Array(21).fill("test")
});
// Beklenen: Error: "En fazla 20 ilgi alanı seçebilirsiniz."

// ❌ Geçersiz ilgi alanı formatı
await tripsApiSafe.create({
  title: "Test",
  interests: ["A".repeat(51)]
});
// Beklenen: Error: "İlgi alanı formatı geçersiz."

// ✅ Geçerli ilgi alanları
await tripsApiSafe.create({
  title: "Test",
  interests: ["history", "culture", "food"]
});

4. Meaningful Error Messages

Özellik: Kullanıcıya anlamlı hata mesajları gösterilir.

Hata Mesajları:

  • "Seyahat oluşturmak için giriş yapmalısınız." (Auth hatası)
  • "Saatlik limit aşıldı. X dakika sonra tekrar deneyin." (Rate limit)
  • "Seyahat başlığı en az 3 karakter olmalıdır." (Validation)
  • "Bitiş tarihi başlangıç tarihinden önce olamaz." (Validation)
  • "Seyahat oluşturulurken bir hata oluştu. Lütfen tekrar deneyin." (DB hatası)

5. Security Audit Logging

Özellik: Tüm güvenlik olayları loglanır.

Log Formatı:

[SECURITY AUDIT] 2026-02-08T10:30:00.000Z | Event: TRIP_CREATE_SUCCESS | User: user-uuid | Details: { tripId, title, destination }

Log Olayları:

  1. TRIP_CREATE_FAILED - Yetkisiz erişim denemesi
  2. TRIP_CREATE_RATE_LIMITED - Rate limit aşımı
  3. TRIP_CREATE_VALIDATION_FAILED - Geçersiz input
  4. TRIP_CREATE_DB_ERROR - Veritabanı hatası
  5. TRIP_CREATE_SUCCESS - Başarılı oluşturma

Test:

// Console'u izle
console.log = jest.fn();

// Başarısız deneme
try {
  await supabase.auth.signOut();
  await tripsApiSafe.create({ title: "Test" });
} catch (error) {
  // Log kontrolü
  expect(console.log).toHaveBeenCalledWith(
    expect.stringContaining('[SECURITY AUDIT]'),
    expect.stringContaining('TRIP_CREATE_FAILED'),
    expect.stringContaining('Unauthorized')
  );
}

Kullanım Örnekleri

Frontend'de Güvenli Kullanım

import { tripsApiSafe } from '@/db/api';
import { toast } from 'sonner';

// ✅ DOĞRU: tripsApiSafe kullan
const handleCreateTrip = async (formData) => {
  try {
    const trip = await tripsApiSafe.create({
      title: formData.title,
      description: formData.description,
      start_date: formData.startDate,
      end_date: formData.endDate,
      destination: formData.destination,
      interests: formData.interests
    });
    
    toast.success('Seyahat başarıyla oluşturuldu!');
    return trip;
  } catch (error) {
    // Kullanıcıya anlamlı hata mesajı göster
    toast.error(error.message);
    console.error('Trip creation error:', error);
  }
};

// ❌ YANLIŞ: tripsApi kullanma (güvensiz)
const handleCreateTripUnsafe = async (formData) => {
  const trip = await tripsApi.create(formData); // Validation yok!
};

Performans Notları

Rate Limiter Memory Management

Rate limiter in-memory Map kullanır. Production'da Redis kullanılması önerilir:

// Gelecek iyileştirme: Redis ile rate limiting
import { Redis } from '@upstash/redis';

const redis = new Redis({
  url: process.env.REDIS_URL,
  token: process.env.REDIS_TOKEN
});

const checkRateLimitRedis = async (userId: string) => {
  const key = `rate_limit:trip_create:${userId}`;
  const count = await redis.incr(key);
  
  if (count === 1) {
    await redis.expire(key, 3600); // 1 saat
  }
  
  if (count > 5) {
    const ttl = await redis.ttl(key);
    throw new Error(`Saatlik limit aşıldı. ${Math.ceil(ttl / 60)} dakika sonra tekrar deneyin.`);
  }
};

Güvenlik Checklist

  • Auth mandatory - Anonim kullanıcılar seyahat oluşturamaz
  • Rate limiting - 5 trip/saat per user
  • Input validation - Tüm alanlar doğrulanır
  • Meaningful errors - Kullanıcıya anlamlı mesajlar
  • Security logging - Tüm olaylar loglanır
  • SQL injection koruması - Input sanitization
  • XSS koruması - String validation
  • Data integrity - Tarih ve konum validasyonu

Sonuç

tripsApiSafe.create() fonksiyonu artık production-ready ve güvenli:

  1. Auth Mandatory: Sadece giriş yapmış kullanıcılar seyahat oluşturabilir
  2. Rate Limiting: Spam ve abuse koruması
  3. Input Validation: Tüm girişler doğrulanır ve sanitize edilir
  4. Error Handling: Kullanıcıya anlamlı mesajlar
  5. Audit Trail: Güvenlik olayları loglanır

Kullanım: Frontend'de her zaman tripsApiSafe.create() kullanın, tripsApi.create() kullanmayın!