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

197 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Clerk Üyelikleri Database'de Görünmüyor - Çözüm Kılavuzu
## Sorun
Clerk ile yapılan üyelikler database'de görünmüyor.
## Kök Neden
LetsGoCappadocia uygulaması **iki farklı yöntemle** Clerk kullanıcılarını database'e kaydeder:
### Yöntem 1: Clerk Webhook (Opsiyonel)
- Kullanıcı Clerk'te kayıt olduğunda webhook tetiklenir
- `clerk-webhook` edge function çalışır
- Profile otomatik olarak database'e eklenir
- **Avantaj**: Kayıt anında profile oluşur
- **Dezavantaj**: Clerk dashboard'da webhook konfigürasyonu gerekir
### Yöntem 2: Client-Side Fallback (Aktif)
- Kullanıcı **ilk kez giriş yaptığında** `useClerkAuthImplementation` hook çalışır
- Hook, Clerk user ID ile database'de profile arar
- Bulamazsa, email ile arar ve Clerk ID'yi bağlar
- Hala bulamazsa, **yeni profile oluşturur**
- **Avantaj**: Webhook olmadan çalışır
- **Dezavantaj**: Kullanıcı en az bir kez giriş yapmalı
## Mevcut Durum Analizi
### Database'deki Profiller
```sql
SELECT id, email, username, role, clerk_user_id, created_at
FROM profiles
ORDER BY created_at DESC;
```
Sonuç:
- 2 profil var
- 1 tanesi Clerk ID'ye sahip (cappadociaturkeytour@gmail.com)
- 1 tanesi Clerk ID'siz (admin@letsgocappadocia.com)
### Sonuç
✅ Clerk entegrasyonu **çalışıyor**
✅ Client-side fallback **aktif**
⚠️ Webhook **muhtemelen yapılandırılmamış**
## Çözüm: Kullanıcıların Giriş Yapması Gerekiyor
### Senaryo 1: Yeni Kayıt Olan Kullanıcı
1. Kullanıcı Clerk ile kayıt olur
2. Kayıt sonrası otomatik olarak giriş yapar
3. `useClerkAuthImplementation` hook çalışır
4. Profile database'e eklenir ✅
### Senaryo 2: Daha Önce Kayıt Olmuş Kullanıcı
1. Kullanıcı Clerk'te kayıtlı ama database'de profili yok
2. Kullanıcı giriş yapar
3. `useClerkAuthImplementation` hook çalışır
4. Profile database'e eklenir ✅
### Senaryo 3: Provider Olmak İsteyen Kullanıcı
1. Kullanıcı kayıt olur ve giriş yapar → Profile oluşur (role='user')
2. `/provider-info` sayfasını ziyaret eder
3. "Provider Olarak Kayıt Ol" butonuna tıklar
4. Provider kayıt formunu doldurur
5. `register_provider` RPC çağrılır
6. Role 'provider' olarak güncellenir ✅
7. Admin panelinde görünür ✅
## Webhook Yapılandırması (Opsiyonel)
Eğer kullanıcıların giriş yapmadan önce database'de görünmesini istiyorsanız:
### 1. Clerk Dashboard Ayarları
1. [Clerk Dashboard](https://dashboard.clerk.com) → Webhooks
2. "Add Endpoint" butonuna tıklayın
3. Endpoint URL: `https://[YOUR_SUPABASE_PROJECT].supabase.co/functions/v1/clerk-webhook`
4. Events seçin:
-`user.created`
-`user.updated`
-`user.deleted`
5. Webhook Secret'i kopyalayın
### 2. Supabase Secret Ayarları
```bash
# Supabase Dashboard → Project Settings → Edge Functions → Secrets
CLERK_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxx
```
### 3. Edge Function Deploy
Edge function zaten deploy edildi:
```bash
✅ clerk-webhook function deployed
```
### 4. Test
1. Yeni bir kullanıcı kayıt edin
2. Database'i kontrol edin:
```sql
SELECT * FROM profiles WHERE clerk_user_id IS NOT NULL ORDER BY created_at DESC LIMIT 5;
```
## Kod Akışı
### useClerkAuthImplementation Hook (src/hooks/useAuth.ts)
```typescript
// 1. Clerk user ID ile ara
let { data } = await supabase
.from('profiles')
.select('*')
.eq('clerk_user_id', clerkUser.id)
.maybeSingle();
// 2. Bulunamazsa, email ile ara ve Clerk ID'yi bağla
if (!data && clerkUser.primaryEmailAddress?.emailAddress) {
const { data: emailData } = await supabase
.from('profiles')
.select('*')
.eq('email', email)
.maybeSingle();
if (emailData) {
// Mevcut profile'a Clerk ID'yi ekle
await supabase
.from('profiles')
.update({ clerk_user_id: clerkUser.id })
.eq('id', emailData.id);
}
}
// 3. Hala bulunamazsa, yeni profile oluştur
if (!data) {
await supabase
.from('profiles')
.insert({
clerk_user_id: clerkUser.id,
email: email,
username: clerkUser.username || email.split('@')[0],
full_name: `${clerkUser.firstName} ${clerkUser.lastName}`,
role: 'user',
is_active: true
});
}
```
## Test Senaryoları
### Test 1: Yeni Kullanıcı Kaydı
1. ✅ Clerk ile kayıt ol
2. ✅ Otomatik giriş yap
3. ✅ Profile database'de oluşur
4. ✅ Admin panelinde görünür (eğer provider ise)
### Test 2: Mevcut Kullanıcı Girişi
1. ✅ Clerk ile giriş yap
2. ✅ Profile database'de oluşur (yoksa)
3. ✅ Clerk ID bağlanır (varsa)
### Test 3: Provider Kaydı
1. ✅ User olarak giriş yap
2. ✅ Provider kayıt formunu doldur
3. ✅ Role 'provider' olur
4. ✅ Admin panelinde görünür
## Sık Sorulan Sorular
### S: Kullanıcı kayıt oldu ama database'de yok?
**C**: Kullanıcı en az bir kez giriş yapmalı. Kayıt sonrası otomatik giriş yapılıyor, bu yüzden normal şartlarda sorun olmamalı.
### S: Webhook gerekli mi?
**C**: Hayır. Client-side fallback yeterli. Webhook sadece kayıt anında profile oluşturmak için kullanılır.
### S: Admin panelinde provider görünmüyor?
**C**:
1. Kullanıcı giriş yaptı mı? → Giriş yapmalı
2. Provider kaydı yaptı mı? → `/provider-info` sayfasından kayıt olmalı
3. `admin_provider_stats` view'ı güncel mi? → Migration uygulandı
### S: Email ile arama neden yapılıyor?
**C**: Eğer kullanıcı daha önce başka bir yöntemle (örn: demo login) kayıt olduysa, Clerk ID'si olmayabilir. Email ile bulup Clerk ID'yi bağlıyoruz.
## Öneriler
### Üretim Ortamı İçin
1. ✅ Webhook yapılandırın (kayıt anında profile oluşur)
2. ✅ CLERK_WEBHOOK_SECRET'i ayarlayın
3. ✅ Webhook endpoint'ini test edin
4. ⚠️ Client-side fallback'i kaldırmayın (yedek olarak kalmalı)
### Geliştirme Ortamı İçin
1. ✅ Client-side fallback yeterli
2. ✅ Webhook opsiyonel
3. ✅ Test kullanıcıları giriş yapmalı
## Sonuç
**Clerk entegrasyonu çalışıyor.** Kullanıcılar kayıt olduktan sonra giriş yaptıklarında otomatik olarak database'e ekleniyor. Provider olmak isteyen kullanıcılar `/provider-info` sayfasından kayıt olabilir ve admin panelinde görünür.
Webhook yapılandırması opsiyoneldir ve sadece kayıt anında profile oluşturmak için kullanılır. Mevcut client-side fallback mekanizması tüm senaryoları kapsar.