Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Yazı Tipi BoyutlandırıcıAa
  • Anasayfa
  • Teknoloji
    • Siber Güvenlik
    • Yapay Zeka
    • Donanım
    • Bilim
  • Yazılım
  • Savunma & İstihbarat
  • Oyun
  • Yaşam
    • Finans
    • Sinema
    • Dünyadan Haberler
  • İş Birliği
Okuma: SaaS altyapıma bir denetim günlükü çıkardım ve inceleme yanlış bir şeyi kaydettiğini tespit etti.
Paylaş
Yazı Tipi BoyutlandırıcıAa
Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Ara
Bizi Takip Et
  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti
© 2026 Teknomers. All Rights Reserved.

Anasayfa » SaaS altyapıma bir denetim günlükü çıkardım ve inceleme yanlış bir şeyi kaydettiğini tespit etti.

Yazılım

SaaS altyapıma bir denetim günlükü çıkardım ve inceleme yanlış bir şeyi kaydettiğini tespit etti.

teknomers
Son güncelleme: 4 Haziran 2026 00:05
teknomers
Paylaş
Paylaş

Açık kaynak bir Laravel CRM uygulamasını modül bazında yeniden kullanılabilir bir SaaS çekirdeğine çıkarma serisinin bir sonraki kısmına hoş geldiniz. Şu ana kadar: temel katman, Fortify üzerinde kimlik doğrulama, çok kiracılık ve roller & izinler. Şimdi v0.5.0 aşamasındayız: aktivite kaydı.

<p>Bu modülün ne olduğu konusunda açık olmak istiyorum, çünkü abartma yapmak oldukça kolay.</p>

<h2>
    <a name="i-did-not-invent-an-audit-log" href="#i-did-not-invent-an-audit-log">
    </a>
    Ben bir denetim kaydı icat etmedim
</h2>

<p>Kayıt işlemi <code>spatie/laravel-activitylog</code> üzerinde gerçekleşiyor. Harika bir paket ve kendi denetim kaydımı yazmak gereksiz olurdu. Bu yüzden bunu yapmadım.</p>

<p>Benim çıkardığım şey, spatie'nin kutudan çıkışta sunduğu şeylerin dışında kalanları, etrafına sarmalayarak ekleyip özelleştirdim:</p>

<ul>
    <li>Her kayıt, yalnızca "model X değişti" demek yerine <strong>cihaz, IP, rota, HTTP yöntemi ve coğrafi konumu</strong> içerir.</li>
    <li>Hepsini okuyabilen tek bir <strong>süper yönetici görüntüleyici</strong>.</li>
    <li>Kendi olaylarını kayıt eden bir yapılandırma kaydı (kimlik doğrulama, kiracılık) ve ev sahibi kendi alan olaylarını aynı şekilde ekler.</li>
</ul>

<p>Değer, entegrasyonda yatıyor, depolama işlemlerinde değil. Bunu her yazımda belirtiyorum çünkü kamuya açık inşanın amacı, bitmemiş bir arabanın sadece motorunu gönderirken onu bitmiş gibi göstermemektir.</p>

<h2>
    <a name="the-one-decision-worth-explaining-this-is-not-a-tenant-feature" href="#the-one-decision-worth-explaining-this-is-not-a-tenant-feature">
    </a>
    Açıklanmayı gerektiren bir karar: bu bir kiracı özelliği değil
</h2>

<p>CRM’imde, aktivite kaydı bir platform operatör aracıdır. O kaydı okuyan kişi <em>ben</em>, operatörüm, şirket sahibi değil. Bu nedenle kayıt küresel bir yapıdadır. <code>company_id</code> yok. Süper yönetici, her kiracı arasında her şeyi görebilir; şirkete ait bir sahip bunu asla göremez.</p>

<p>Bu küçük bir şey gibi görünebilir ama tüm modülü şekillendirdi. Yanlış yapılacak bir kiracı ayarı yok, her şirkete özgü bir filtrasyon yok, bir şirketin diğerinin kaydını okuma riski yok. Erişim kuralı tek bir soruya indirgeniyor: süper yönetici misin? Ve süper yönetici, kimlik doğrulama aşamasından bir kimlik işareti olarak tek bir sınıf aracılığıyla çözülüyor; kazara verilmeyen bir rol değil.</p>

<p>Ayrıca, bu modül sessizce daha büyük bir şeyin ilk dilimini sunuyor: bir platform operatörü konsolu. Aktivite kaydı bu konsolun ilk ekranı. Yönetici arayüzünü kasıtlı olarak küçük tuttum (bir başlık, bir "süper yönetici" işareti, bir alan) böylece bu haftayı konsolun tamamını inşa etmeye çalışmış gibi göstermiyorum.</p>

<h2>
    <a name="the-context-wrapper" href="#the-context-wrapper">
    </a>
    Bağlam sarmalayıcı
</h2>

<p>Temel, her kayıtta istek bağlamını bir yerden kaydediyor ve cihazı, kimlik doğrulama aşamasındaki parmak izi sözleşmesine göre çözüyor (ikinci bir kullanıcı aracısı ayrıştırıcı değil) ve her şeyi saklamadan önce gizli bilgileri düzeltip düzenliyor.<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="k">public</span> <span class="k">function</span> <span class="n">forRequest</span><span class="p">(</span><span class="kt">?Request</span> <span class="nv">$request</span> <span class="o">=</span> <span class="kc">null</span><span class="p">):</span> <span class="kt">array</span>

{
$request ??= request();
$device = $this->deviceResolver->resolve($request);

<span class="k">return</span> <span class="p">[</span>
    <span class="s1">'user_ip'</span> <span class="o">=&gt;</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="nf">ip</span><span class="p">(),</span>
    <span class="s1">'user_device_type'</span> <span class="o">=&gt;</span> <span class="nv">$device</span><span class="o">-&gt;</span><span class="n">type</span><span class="p">,</span>
    <span class="s1">'user_os'</span> <span class="o">=&gt;</span> <span class="nv">$device</span><span class="o">-&gt;</span><span class="n">os</span><span class="p">,</span>
    <span class="s1">'user_browser'</span> <span class="o">=&gt;</span> <span class="nv">$device</span><span class="o">-&gt;</span><span class="n">browser</span><span class="p">,</span>
    <span class="s1">'route_name'</span> <span class="o">=&gt;</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="nf">route</span><span class="p">()</span><span class="o">?-&gt;</span><span class="nf">getName</span><span class="p">(),</span>
    <span class="s1">'request_method'</span> <span class="o">=&gt;</span> <span class="nv">$request</span><span class="o">-&gt;</span><span class="nf">getMethod</span><span class="p">(),</span>
    <span class="s1">'full_url'</span> <span class="o">=&gt;</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">redactUrl</span><span class="p">(</span><span class="nv">$request</span><span class="o">-&gt;</span><span class="nf">fullUrl</span><span class="p">()),</span>
    <span class="c1">// ...</span>
<span class="p">];</span>

}

<p>O <code>redactUrl</code> önemli. Bağışlayan, ham URL'yi saklıyordu; bu, bir şifre sıfırlama bağlantısı veya 2FA kodunun bir sorgu dizisinde geçmesi durumunda, denetim tablosuna düz metin olarak yazılmasına neden oluyordu. Paket, saklanan herhangi bir yapılandırılmış PII anahtarının değerini kaydetmeden önce maskelemektedir ve ayrıca (bir gözden geçirme notu, aşağıdaki incelemelerle ilgili daha fazla bilgi) geri kalan URL'yi de bozmadan yapıyor.</p>

<h2>
    <a name="then-the-review-found-it-logging-the-wrong-thing" href="#then-the-review-found-it-logging-the-wrong-thing">
    </a>
    Ardından inceleme, yanlış şeyi kaydettiğini buldu
</h2>

<p>Bu serideki her modül, birleştirilmeden önce bir kod incelemesinden geçmektedir ve şu ana kadar her modül inceleme sırasında gerçek bir hata tespit etmiştir. Bu modülde hata oldukça gizliydi, çünkü kod açıkça doğru görünüyordu.</p>

<p>Bağışlayan, zaten bildiğim bir gerçeği hads etti: hem <code>causer_id</code> hem de <code>subject_id</code> için aynı kullanıcı kimliğini yazıyordu. "Bunu kim yaptı" ve "ne yapıldığı" aynı satıra kaydediliyordu. Bu, bir denetim kaydı için mantıksız, bu yüzden çıkardım: neden olan (causer) eylemi gerçekleştiren, konu (subject) ise eylemin nesnesi olarak ayrı ayrı çözüldü.</p>

<p>Resolver'ım, etkinlikten belirli bir özelliği kontrol ederek konuyu alıyordu:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="k">foreach</span> <span class="p">([</span><span class="s1">'subject'</span><span class="p">,</span> <span class="s1">'company'</span><span class="p">,</span> <span class="s1">'model'</span><span class="p">,</span> <span class="s1">'invitation'</span><span class="p">,</span> <span class="s1">'employee'</span><span class="p">]</span> <span class="k">as</span> <span class="nv">$property</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">isset</span><span class="p">(</span><span class="nv">$event</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$property</span><span class="p">})</span> <span class="o">&amp;&amp;</span> <span class="nv">$event</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$property</span><span class="p">}</span> <span class="k">instanceof</span> <span class="nc">Model</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nv">$event</span><span class="o">-&gt;</span><span class="p">{</span><span class="nv">$property</span><span class="p">};</span>
<span class="p">}</span>

}

<p>Güzel görünüyor. Yazdığım testi geçmeyi başardı; bu test <code>CompanyCreated</code> (sadece bir şirket taşıyan bir olay) kullanıyordu. 'Yeşil'. Gönder!</p>

<p>Yalnızca inceleme, testimin sormadığı bir soruyu sordu: birden fazla model taşıyan bir olay ne olacak?</p>

<p><code>EmployeeRemoved</code>, hem <code>company</code> hem de kaldırılan <code>employee</code>'yi taşır. Döngüm önce <code>company</code>yi kontrol ediyor, bu yüzden "çalışan kaldırıldı" durumunda <strong>şirket</strong> konuyu kaydediyor. Eylemin nesnesi kaldırılan kişidir ve ben kaydederken kaldırılanın nereden kaldırıldığına dair herhangi bir bilgi vermiyorum. Denetleyici "çalışan kaldırıldı, konu: Acme Co" okursa bununla ilgili hiçbir şey öğrenemiyor.</p>

<p>Düzeltme, bir sıralamadan ibaret, artı sonraki kişinin neden sıralamanın önemli olduğunu anlaması için bir yorum:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="c1">// eylemin en belirgin nesnesi kazanır. EmployeeRemoved hem</span>

// company (bağlam) hem de employee (gerçek konu) taşır, bu nedenle belirli varlıklar
// etrafındaki şirkete göre daha önce kontrol edilmelidir.
foreach ([‘subject’, ’employee’, ‘invitation’, ‘model’, ‘company’] as $property) {

<p>Ve <code>EmployeeRemoved</code> olayını ateşleyen ve konunun çalışanın kendisi olduğunu doğrulayan bir regresyon testi. Yine ders: hata, satırda değildi. Hata, testin yalnızca kolay durumu test etmesindeydi.</p>

<h2>
    <a name="a-quieter-one-in-the-geo-path" href="#a-quieter-one-in-the-geo-path">
    </a>
    Coğrafi yolda daha sessiz bir şey
</h2>

<p>Coğrafi konum, kullanıcının IP'si ile üçüncü bir partiyi arayan bir dış çağrıdır, bu yüzden isteğe bağlıdır, önbelleğe alınır ve bir kuyruğa alınmış iş ile çalışır. Özel ve loopback IP'ler yerel olarak yanıtlanır ve asla sunucunun dışına çıkmaz.</p>

<p>İşin <code>failed()</code> işleyicisi "Bilinmiyor" damgasını basarak bir satırın yarım zengin bırakılmasını engeller. Makul. Ancak inceleme, çözücünün hata yumuşak olduğunu belirtti (herhangi bir ağ hatasında "Bilinmiyor" döner ve asla bir hata fırlatmaz), bu nedenle işin gerçekte başarısız olabilmesi tek yol yalnızca <em>veritabanı yazma</em> hatası atıp asıl ülke zaten çözüldükten sonra gerçekleşebilir. Bu durumda <code>failed()</code> doğru coğrafi verileri "Bilinmiyor" ile geçersiz kılacaktır. Düzeltme, yalnızca hiç zenginleştirilmemiş bir satıra "Bilinmiyor" damgasını basmaktır:<br/></p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="k">if</span> <span class="p">(</span><span class="nv">$activity</span><span class="o">-&gt;</span><span class="n">geo_updated_at</span> <span class="o">!==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">return</span><span class="p">;</span> <span class="c1">// zaten zenginleştirildi; iyi veriyi "Bilinmiyor" ile geçersiz kılma</span>
<span class="p">}</span>

<p>Küçük ama bu, yalnızca birinin "bu satıra ulaşan gerçek yol nedir?" sorusunu sorması gerektiğinde göreceğiniz bir şeydir.</p>

<h2>
    <a name="the-modelaudit-trait-fixed" href="#the-modelaudit-trait-fixed">
    </a>
    Model denetim özelliği, düzeltildi
</h2>

<p>Bağışlayan, herhangi bir modelde otomatik oluşturma/güncelleme/silme denetimi için <code>LogsActivity</code> adlı bir özellik göndermişti. Bu üç açıdan bozuktu: üst fonksiyonu çağırmadan spatie'nin boot metodunu geçiyordu (bu nedenle spatie'nin motoru asla çalışmıyordu), var olmayan bir metodu çağırıyor (ilk kayıtta ölümcül) ve her niteliği kaydediyor, kirli fark yerine.</p>

<p>Paket versiyonu, bunların hepsini dışarıda bırakıyor ve spatie'nin yerel makinelerini kullanıyor: neyi kaydedeceğini belirliyor, ardından çağrılan üst sınıf ile çekirdek talebinin bağlamı ile süslüyor. Hiçbir motor geçişi, gerçek eski-yeni farkları, artı her denetim satırında cihaz ve IP bilgisi ile.</p>

<h2>
    <a name="what-it-deliberately-is-not" href="#what-it-deliberately-is-not">
    </a>
    Ne olduğu kasten değildir
</h2>

<p>Her sürümde koyduğum dürüstlük notunu yine yazıyorum. v0.5.0, denetim kaydı arka ucunu ve minimum bir süper yönetici görüntüleyiciyi getiriyor. Tam bir operatör konsolu (istatistik, destek, faturalama ekranları) göndermez; bu ayrılmış aşamalar ile gelir ve aynı yönetici arayüzüne entegre edilir. Her isteği kaydeden yol erişim middleware'i kutunun içerisinde ama varsayılan olarak kapalıdır, çünkü gürültülüdür. Alan olayları (siparişler gönderildi, faturalar ödendi) ev sahibi tarafından kaydedilmekte, çekirdek yalnızca kendi kimlik doğrulama ve kiracılık olaylarını sunmaktadır.</p>

<p>Model denetimi özelliği, her satıra "HTTP 200, başarı" yazıyor, çünkü bir istekteki model kaydı, tanım gereği veritabanına ulaşan bir başarıdır. Bu, yalnızca bu yol için dürüst, uydurduğum bir durum değil.</p>

<h2>
    <a name="tests-and-the-close" href="#tests-and-the-close">
    </a>
    Testler ve kapanış
</h2>

<p>Paket, yeşil durumda: aktivite-kayıt testi, causer/subject ayrımını, yukarıdaki iki düzeltmeyi, PII düzenlemeyi (inceleme ile ortaya çıkan URL özen haddeleri dahil), asenkron coğrafi işleme ve isteğe bağlı olma durumunu, süper yönetici kuralını ve model denetimi farkını kapsamaktadır; ayrıca görüntüleyicinin düşman bir kullanıcı aracısını inaktif metin olarak ve asla işaretleme olarak döndüğünü kanıtlayan bir frontend testi bulunmaktadır. Ev sahibi entegrasyon testi, gerçek bir şirket oluşturma olayının, canlı middleware yelpazesinden geçerek kayıtta başarıyla yer aldığını kanıtlamaktadır.</p>

<p>Tekrar eden bir model: çıkarım, hataların sıkça nerede olduğudur. Hatalar, ikinci bir geçişin, testinizin sormadığı bir soruyu sormasıyla ortaya çıkar. "İki modeli olan olay ne olacak" sorusu, kaydın yanlış bir konuyu sessizce kaydedeceğini buldu ve uzun süre doğru göründü.</p>

<p>Sonraki aşama, navigasyon ve operatör konsolunun geri kalanıdır.</p>

<p>Paket, GitHub'da halkadır: <a href="https://github.com/dmitryisaenko/larafoundry" target="_blank" rel="noopener noreferrer">https://github.com/dmitryisaenko/larafoundry</a></p>

Kaynak: Orijinal Makale

Laravel 12 ile Vite Kullanarak Bootstrap 5 Nasıl Kurulur
Artisan Kaydırmaktan Bıktınız mı? php artisan list –mine ile Tanışın
Rollerin sabit kodlanması, SaaS ölçeklenebilirliği için gizli bir tehlikedir.
Gerçek Zamanlı İkili Opsiyonlar Platformu Kurmanın Zor Kısmı Grafik Değildi
Rust için Laravel benzeri bir Web Framework’u Geliştirdim
Bu Makaleyi Paylaş
Facebook Bağlantıyı Kopyala Yazdır
Paylaş
Önceki Makale GTA 6 Sırlarını WWE 2K26’da Öğrenme Fırsatı
Sonraki Makale Vampire The Masquerade Bloodlines 2 için yeni içerik çok yakında geliyor

Sanal Medya

FacebookBeğen
452Takip Et
PinterestSabitle
237Takip Et

Son Eklenenler

Intel yeni oyun destekli iBOT yazılımını 7 oyunla genişletti, %27’ye kadar iyileşme sundu
Donanım
GTA 6’nın Barbenheimer’ı: Barbie Derlemesi Kasım’da Geliyor
Oyun
Restoran Yönetiminde Devrim Yaratacak Kod Güncellemeleri
Oyun
Kritik: NSO Group’un Yeni WhatsApp Phishing Saldırısı ve Yasal Süreçler
Siber Güvenlik
Apple ebeveynlere çocukların iPhone kullanımlarında yeniden kontrol sağlıyor
Genel
Apple Ekran Süresini Yeniden Tasarlıyor ve Çocuk Kontrollerini Gözden Geçiriyor
Liste
//

Siber güvenlik, yapay zeka ve savunma sanayiinden; finans ve sinema dünyasına uzanan geniş bir yelpaze. Teknomers; teknoloji, strateji ve yazılım dünyasını sade bir dille sizlerle buluşturuyor.

Kurumsal

  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti

Kategoriler

  • Teknoloji
  • Oyun
  • Sinema
  • Siber Güvenlik
  • Bilim
  • Finans
  • Dünyadan Güncel Haberler

Populer

  • TV'de Ücretsiz İzlenebilen Şifresiz Erotik Kanallar (2025 Güncel Frekans Listesi)

  • The Last of Us PC Kontrolleri: Hızlı Silah Değiştirme ve Tüm Tuşlar (2025)

  • Hogwarts Legacy'de Odaklanma İksiri Nasıl Yapılır?

Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Bizi Takip Et
© 2026 Teknomers. All Rights Reserved.
Welcome Back!

Sign in to your account

Kullanıcı Adı veya E-posta Adresi
Şifre

Şifrenizi mi unuttunuz?