İçeriğe geç

Satır düzeyi erişim ve kiracılar

CPalius'ta "bu kullanıcı bu kaydı görebilir mi?" sorusu sorgu çalışmadan önce SQL'e çevrilir. Liste ekranları satır satır yetki sormaz; WHERE koşulu zaten yalnızca görülebilir satırları getirir. Üç mekanizma birlikte çalışır.

1. .own / .any kapsamı: QueryScopeApplier

Yetenekler iki sonekle kurulur: node.post.edit.any (herkesin yazısı) ve node.post.edit.own (yalnızca kendi yazısı). QueryScopeApplier::apply() bir sorguya kapsam ekler:

Kullanıcının sahip olduğu Eklenen koşul
.any Koşul eklenmez (tüm satırlar)
yalnızca .own sahip alanı = ben
ikisi de yok 1 = 0 (boş sonuç)

Kural şudur: yetkisiz kullanıcı hiçbir zaman süzülmemiş tablo görmez. Hiçbir koşulun uygulanmadığı bir sonuç yoktur; yetki yoksa sonuç boştur.

$qb = $repository->createQueryBuilder('p');
$this->scope->apply($qb, 'p', 'node.post.edit', ownerField: 'author');

Üçüncü parametre yetenek kökü (soneksiz), ownerField sahip sütunudur.

2. Tek kayıt için izin: EntityAccessManager

Bazen "bu kullanıcı yalnızca şu kaydı düzenleyebilsin" gerekir. EntityAccessManager kayıt bazlı izin kayıtları (grant) tutar; yetenek ad alanı aynıdır, paralel bir sistem yoktur:

$access->grantToUser('node', $id, 'node.post.edit', $userId);
$access->grantToRole('node', $id, 'node.post.edit', 'editor');
$access->grantToAnyone('node', $id, 'node.post.view');
$access->revokeFromUser('node', $id, 'node.post.edit', $userId);

İki özelliği önemlidir:

  • Yeniden oluşturma adımı yoktur. Her izin satırı yazıldığı anda tek başına doğrudur; bir modül, görünürlük değiştiği an izni yazar.
  • Sorguya katlanır. buildScopeCondition() izinleri, çağıranın sorgusuna ilişkili EXISTS alt sorgusu olarak ekler. QueryScopeApplier kayıt izinlerini de bu yolla hesaba katar: .own yetkisi olmayan ama bu kayda izni olan kullanıcı kaydı yine görür.
Tarayıcıda arayüz yok

Çekirdek, tek bir kaydı başkasıyla paylaşma arayüzü sunmaz; yalnızca mekanizmayı verir. Notlar modülü bunun örneğidir: kendi küçük paylaşım tablosu ve NoteAccess hizmeti ile aynı fikri uygular.

3. Çok kiracılı veri: TenantFilter

#[CpResource(multiTenant: true)] taşıyan bir varlığın her sorgusuna otomatik olarak tenant_id = :tenant_id eklenir. Bu bir Doctrine SQLFilter'dır:

  • Yalnızca multiTenant: true işaretli varlıklara uygulanır; diğerlerine dokunmaz.
  • Parametre verilmemişse hiçbir koşul eklemez. Filtre, etkinleştirilip kiracı kimliği tanımlanana kadar kapalıdır; bu yüzden tek kiracılı sitede maliyeti yoktur.
  • Kiracı koşulu, kodunuzdaki her sorguda tekrar yazılmaz; unutulması mümkün değildir.

Ne zaman hangisi

İhtiyaç Araç
"Kendi içeriğimi/herkesinkini" listelemek QueryScopeApplier (.own/.any)
Bir kaydı belirli kişiye ya da role açmak EntityAccessManager
Müşteri başına yalıtılmış veri multiTenant: true + TenantFilter
Modüle özgü paylaşım (not, belge) Kendi tablonuz + sorguya çevrilen erişim sınıfı (Notlar örneği)

Güvenlik notları

  • Erişimi her eylemde denetleyin: kimliğini tahmin eden kullanıcı için kayıt bulunmamış gibi 404 döndürün (403 varlığı ele verir).
  • Listede kapsamı SQL'e çevirmek, şablonda is_granted ile süzmekten hem daha güvenli hem daha hızlıdır; süzülmüş satırlar sayfalamayı da bozmaz.
  • Menüden gizlemek erişimi kapatmaz; bkz. Menü ve yetkiler.
Son güncelleme: 13.10.2026