Skip to content

Instantly share code, notes, and snippets.

@mcihad
Created July 20, 2026 11:05
Show Gist options
  • Select an option

  • Save mcihad/591c921e2f1be8a3ef7a40b2df8ca49a to your computer and use it in GitHub Desktop.

Select an option

Save mcihad/591c921e2f1be8a3ef7a40b2df8ca49a to your computer and use it in GitHub Desktop.
update

Düzeltme: Kullanıcı oluşturulduğunda UserSetting kaydı açılmıyor

Etkilenen bileşen: Sunucu (ASP.NET Core) Mobil tarafta değişiklik gerekmez.


1. Sorun

user_settings tablosunda her kullanıcı için bir satır olması gerekiyor, ancak bu satır kullanıcı oluşturulurken açılmıyor. Kayıt yalnızca iki yerde, geç (lazy) olarak yaratılıyor:

Metot Dosya Tetikleyen uç
UserService.GetSetting() Services/UserService.cs (satır 81-97) GET /api/AccountApi/Settings
UserService.UpdateSetting() Services/UserService.cs (satır 111-130) POST /api/AccountApi/Settings

Mobil uygulamada bu ucu çağıran tek yer Ayarlar ekranıdır (lib/pages/settings_page.dart). Giriş akışında çağrılmaz. Yani satır, kullanıcı mobil uygulamada Ayarlar ekranını ilk kez açtığında oluşur. Yönetim panelinden açılan kullanıcıda hiç oluşmaz.

Görünen belirti

Asıl sorun eksik satırın kendisi değil, sonucudur. Services/UserService.cs satır 48-52:

var setting = await _context.UserSettings.FirstOrDefaultAsync(x => x.UserId == userId);
if (setting == null)
{
    return false;      // ← kayıt yoksa "bildirim istemiyor" sayılıyor
}

UserSetting modelinde tüm alanların varsayılanı true'dur (bildirimler açık), ama kayıt yokken bu metot false döner. MessageService de bunu bir kapı olarak kullanır.

Sonuç: Yeni açılan bir kullanıcı, mobil uygulamada Ayarlar ekranını bir kez açana kadar hiçbir bildirim almaz — yalnızca NotifikasyonTip.Always ile gönderilenler geçer. "Kullanıcı Oluşturuldu" SMS'i Always olduğu için gider, sonrası sessiz kalır.


2. Yapılacak Değişiklikler

Üç değişiklik var. Üçü de uygulanmalıdır:

  • Değişiklik A — kalıcı çözüm (yeni kullanıcılarda satır oluşsun)
  • Değişiklik B — emniyet supabı (satır yoksa bile bildirim gitsin)
  • Değişiklik C — mevcut kullanıcıları onarır (tek seferlik SQL)

Değişiklik A — Kullanıcı oluşturulurken UserSetting satırını da aç

A.1 — Yönetim panelinden kullanıcı oluşturma

Dosya: Sunucu/Sivasbeltr.WorkCollab.Web/Controllers/AppUsersController.cs Yer: Create metodu, satır 104'ün hemen ÖNCESİNE (rol atamasını yapan if bloğu bittikten sonra, var message = ... satırından önce).

Mevcut kod şöyle görünüyor (satır 103-105):

                    }
                    var message = $"Randevu sisteminde kullanıcı kaydınız oluşturuldu. Kullanıcı adı: {user.UserName} Şifre: {model.Password}";
                    await _messageService.CreateAsync(

Araya eklenecek kod — sonuç şöyle olmalı:

                    }

                    // Kullanici icin varsayilan bildirim ayarlarini olustur.
                    // UserSetting modelindeki tum alanlarin varsayilani true'dur (bildirimler acik).
                    if (!await _context.UserSettings.AnyAsync(x => x.UserId == user.Id))
                    {
                        _context.UserSettings.Add(new UserSetting { UserId = user.Id });
                        await _context.SaveChangesAsync();
                    }

                    var message = $"Randevu sisteminde kullanıcı kaydınız oluşturuldu. Kullanıcı adı: {user.UserName} Şifre: {model.Password}";
                    await _messageService.CreateAsync(

Not: Gerekli using satırları dosyada zaten mevcuttur (Microsoft.EntityFrameworkCore satır 10, Sivasbeltr.WorkCollab.Application.Models satır 12). _context alanı da sınıfta hazırdır (satır 25). Ek using gerekmez.

A.2 — İlk kurulumdaki admin hesabı

Dosya: Sunucu/Sivasbeltr.WorkCollab.Web/Data/DataSeeder.cs Yer: EnsureAdmin metodu, satır 71'den sonra (rol atamalarının hemen ardından, } kapanışından önce).

Mevcut kod (satır 69-72):

                await userManager.CreateAsync(user, AdminPassword);
                await userManager.AddToRoleAsync(user, UserRoles.Admin);
                await userManager.AddToRoleAsync(user, UserRoles.Sistem);
            }

Şu hale getirin:

                await userManager.CreateAsync(user, AdminPassword);
                await userManager.AddToRoleAsync(user, UserRoles.Admin);
                await userManager.AddToRoleAsync(user, UserRoles.Sistem);

                // Varsayilan bildirim ayarlarini olustur.
                var context = serviceProvider.GetRequiredService<AppDbContext>();
                if (!await context.UserSettings.AnyAsync(x => x.UserId == user.Id))
                {
                    context.UserSettings.Add(new UserSetting { UserId = user.Id });
                    await context.SaveChangesAsync();
                }
            }

Not: DataSeeder.cs dosyasının başında using Microsoft.EntityFrameworkCore; (satır 2) ve using Sivasbeltr.WorkCollab.Application.Models; (satır 4) zaten var. AppDbContext aynı namespace'te (Sivasbeltr.WorkCollab.Web.Data) olduğu için ek using gerekmez.


Değişiklik B — Kayıt yoksa bildirim engellenmesin

Dosya: Sunucu/Sivasbeltr.WorkCollab.Web/Services/UserService.cs Yer: HasReceiveNotification metodu, satır 48-52.

Mevcut kod:

            var setting = await _context.UserSettings.FirstOrDefaultAsync(x => x.UserId == userId);
            if (setting == null)
            {
                return false;
            }

Yeni hali:

            var setting = await _context.UserSettings.FirstOrDefaultAsync(x => x.UserId == userId);
            if (setting == null)
            {
                // Ayar kaydi yoksa kullanici henuz hicbir tercihte bulunmamis demektir.
                // UserSetting modelindeki varsayilanlar true oldugu icin bildirim GONDERILIR.
                // (Onceki davranis false idi; bu, ayar kaydi olusmamis kullanicilarin
                //  hicbir bildirim almamasina yol aciyordu.)
                return true;
            }

⚠️ Bu bir davranış değişikliğidir. Bu düzeltmeden sonra, user_settings satırı olmayan mevcut kullanıcılar bildirim almaya başlayacaktır. Beklenen ve doğru davranış budur, ancak kullanıcılar için ani bir değişiklik olacağı için bilgilendirme yapmanız iyi olur. Değişiklik C uygulanırsa zaten satırsız kullanıcı kalmaz ve bu kod yolu bir daha çalışmaz; B yine de ileride oluşabilecek durumlara karşı emniyet supabı olarak kalmalıdır.


Değişiklik C — Mevcut kullanıcılar için tek seferlik veri onarımı

A ve B kod değişiklikleridir, geçmişte açılmış kullanıcıları düzeltmezler. Aşağıdaki SQL, satırı eksik olan tüm kullanıcılar için varsayılan ayar kaydını oluşturur.

Önce yedek alın:

pg_dump -U <kullanici> -d workcollab > workcollab_yedek_$(date +%F).sql

Ardından PostgreSQL üzerinde çalıştırın:

INSERT INTO user_settings (
    user_id,
    hide_old_agendas,
    agenda_on_created, agenda_on_organized, agenda_on_deleted, agenda_on_updated,
    agenda_on_status_change, agenda_on_image_upload, agenda_on_note_added,
    agenda_on_postponed, agenda_on_flower_sent, agenda_on_flower_deleted,
    request_on_created, request_on_organized, request_on_deleted, request_on_updated,
    request_on_file_attached, request_on_status_change, request_on_note_added,
    request_on_remittance, request_on_added_to_agenda
)
SELECT
    u.id,
    true,
    true, true, true, true,
    true, true, true,
    true, true, true,
    true, true, true, true,
    true, true, true,
    true, true
FROM "AspNetUsers" u
WHERE NOT EXISTS (
    SELECT 1 FROM user_settings s WHERE s.user_id = u.id
);

Tablo adı notu: Kullanıcı tablosunun adı "AspNetUsers" şeklinde büyük harflidir ve PostgreSQL'de çift tırnak içinde yazılmalıdır. Kolon adları ise snake_case'tir (u.id).

Doğrulama — aşağıdaki sorgu 0 dönmelidir:

SELECT COUNT(*)
FROM "AspNetUsers" u
WHERE NOT EXISTS (SELECT 1 FROM user_settings s WHERE s.user_id = u.id);

Kullanıcı ve ayar sayılarının eşitliğini de kontrol edebilirsiniz:

SELECT (SELECT COUNT(*) FROM "AspNetUsers")  AS kullanici_sayisi,
       (SELECT COUNT(*) FROM user_settings)  AS ayar_sayisi;

3. Uygulama Sırası

  1. Veritabanı yedeği alın.
  2. Değişiklik C'deki SQL'i çalıştırın (mevcut kullanıcılar onarılır).
  3. Değişiklik A ve B'yi koda uygulayın.
  4. Derleyin: dotnet build → hata olmamalı.
  5. Uygulamayı yeniden yayına alın (dotnet publish + servis restart).

4. Test

  1. Yönetim panelinden yeni bir kullanıcı oluşturun.
  2. Veritabanında satırın oluştuğunu doğrulayın:
    SELECT * FROM user_settings WHERE user_id = <yeni_kullanici_id>;
    → Bir satır dönmeli, tüm boolean alanlar true olmalı.
  3. Bu kullanıcıyla mobil uygulamaya giriş yapın (FCM token'ın sunucuya gitmesi için).
  4. Bu kullanıcıya bildirim üretecek bir işlem yapın (örn. ajanda oluşturma).
  5. messages tablosunda kaydın oluştuğunu ve is_success = true olduğunu doğrulayın:
    SELECT id, title, is_success, fail_message FROM messages ORDER BY id DESC LIMIT 5;
  6. Mobil uygulamada Ayarlar ekranını açın — ayarlar görünmeli, değiştirip kaydettiğinizde user_settings satırı güncellenmeli (yeni satır oluşmamalı).

5. İlgili Not (ayrı konu, acil değil)

UserSetting.UserId için tanımlı bir foreign key / ilişki yokturAppDbContext.cs satır 31'de yalnızca DbSet<UserSetting> tanımlıdır. Bu nedenle:

  • Bir kullanıcı silindiğinde user_settings satırı öksüz kalır (silinmez).
  • Veritabanı düzeyinde bütünlük garantisi yoktur.

İleride düzeltmek isterseniz AppDbContext.OnModelCreating içinde AppUser ile UserSetting arasında HasOne/WithOne ilişkisi ve OnDelete(DeleteBehavior.Cascade) tanımlayıp yeni bir migration üretmeniz gerekir. Bu, mevcut sorunu çözmek için gerekli değildir; yukarıdaki A/B/C değişiklikleri bağımsız olarak çalışır.

Öksüz kalmış satırları temizlemek isterseniz:

DELETE FROM user_settings s
WHERE NOT EXISTS (SELECT 1 FROM "AspNetUsers" u WHERE u.id = s.user_id);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment