mcp yetki problemi

This commit is contained in:
Sedat ÖZTÜRK 2026-09-29 17:55:13 +03:00
parent a46e12f986
commit 019f1ddab4
4 changed files with 63 additions and 11 deletions

View file

@ -701,6 +701,11 @@ Kısa ve karar odaklı yaz; talebi tekrar anlatma.
üç seviyedir; analiz talebin istemediği bir ara seviye eklemez. Talep menü yolunu yazıyorsa
(başlıkta ya da açıklamada) o yol girdidir ve seviye seviye aynen alınır. Wizard karşılığı:
ekranın bir üstü `MenuParentCode`, daha üstündekiler `MenuParentPath` (iki seviyede boş, §4.4).
**Yetki ağacı menü ağacıyla aynıdır**: deploy, izin grubu dışındaki her menü seviyesini aynı
kodlu ara yetki yapar ve ekranın okuma yetkisini onun altına yazar. Analiz bunu menü tablosunun
altında tek satırda gösterir — `Yetki: {İzin grubu} › {Ara yetki} › {ListFormCode}` — ve her ara
seviyenin yetkisi için Var / Yeni yazar (var olan `Abp.Identity.Permissions.json`'dan okunur).
Yetkinin yerini menüden ayrı seçen bir wizard alanı yoktur; yetki dalı menü yoluyla birlikte değişir.
Aynı üst menü altındaki ekranlar **bağımlılık sırasıyla** yazılır: başka bir ekranın lookup
kaynağı olan (tanım) ekran, onu kullanan ekranın üstündedir. Menüdeki sıra deploy sırasından
gelir; madde 9'daki üretim planı da aynı sırayla yazılır.
@ -2135,7 +2140,7 @@ ardından `ListFormSeedDataApplier` menü/yetki/dil satırlarını kurar (§4.0)
1. Konfigürasyon doğrulama
2. Menü kaydı (`CreateMenu: false` ise atlanır)
3. Dil metinleri
4. İzin grubu + yetkiler
4. İzin grubu + yetkiler (okuma yetkisi menü dalındaki ara yetkinin altına, §0.12 Menü yeri)
5. List yolunda: veri kaynağı → ListForm → alan grupları · Custom yolunda: bileşen bağlama
6. Deploy + tamamlandı

View file

@ -943,7 +943,13 @@ Sıra **kardeşler arasındadır**: her üst yetkinin altında 1'den başlar, gr
kendi aralarında 1'den. `PlatformPermissionAppService` sıralama anahtarını kökten yaprağa üst yetki
zincirinden kurar, böylece çocuk her zaman ebeveyninin altında kalır. Değerler seed dosyalarındaki
`Order` alanında tutulur ve Permissions / Permission Groups ekranlarından düzenlenebilir.
Wizard deploy'u yeni grubu ve grubun yeni kök yetkisini (seed satırı olarak) veritabanı ile seed
**Yetki ağacı menü ağacını izler.** Wizard ekranın okuma yetkisini menüde durduğu dalın altına
yazar: üst menü zincirindeki (`MenuParentPath` + `MenuParentCode`) her seviye, izin grubunun
kendisi hariç, aynı kodlu bir ara yetkidir (`İnsan Kaynakları › Tanımlamalar › Ekran` →
`App.Hr.Definitions › App.Hr.Doctor`). Var olan ara yetki kullanılır, eksik olan menü seviyesinin
görünen adıyla wizard'a ait üretilir; başka bir gruptaki aynı adlı yetki atlanır. Menüsüz wizard'da
(`CreateMenu: false`) okuma yetkisi grubun köküne yazılır.
Wizard deploy'u yeni grubu ve yeni yetkileri (seed satırı olarak) veritabanı ile seed
dosyasındaki kardeşlerin en büyük sırasının bir fazlasıyla, alt yetkileri `WizardSeedRowKeys.ChildPermissions` dizilimiyle
(List: Create/Update/Delete/Export/Import/Note, Custom: Create/Update/Delete) 1'den yazar
(`ListFormWizardAppService.WritePermissionGroupAsync` / `WritePermissionRowsAsync`).

View file

@ -424,21 +424,61 @@ public class ListFormWizardAppService(
inserted.PermissionNames.Add(name);
}
if (IsOwnable(code))
{
var existingRow = rows.Find(WizardSeedRowStore.PermissionFile, "Name", code);
var order = existingRow != null
static bool Same(string? a, string? b) => string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
// Kardesler arasindaki sira; parent bos ise grubun kok yetkileri. Zincirde az once yazilan
// seviye de sirada yer tutar.
int NextOrder(string name, string? parent) =>
rows.Find(WizardSeedRowStore.PermissionFile, "Name", name) is { } existingRow
? WizardSeedRowStore.Int(existingRow, PlatformConsts.Permissions.Order)
: dbPermissions.Where(p => string.IsNullOrWhiteSpace(p.ParentName)).Select(p => p.GetProperty<int>(PlatformConsts.Permissions.Order))
: dbPermissions.Where(p => Same(p.ParentName ?? string.Empty, parent ?? string.Empty) && !Same(p.Name, name))
.Select(p => p.GetProperty<int>(PlatformConsts.Permissions.Order))
.Concat(rows.Rows(WizardSeedRowStore.PermissionFile)
.Where(r => string.Equals(WizardSeedRowStore.Text(r, "GroupName"), groupName, StringComparison.OrdinalIgnoreCase) &&
string.IsNullOrWhiteSpace(WizardSeedRowStore.Text(r, "ParentName")))
.Where(r => Same(WizardSeedRowStore.Text(r, "GroupName"), groupName) &&
Same(WizardSeedRowStore.Text(r, "ParentName") ?? string.Empty, parent ?? string.Empty) &&
!Same(WizardSeedRowStore.Text(r, "Name"), name))
.Select(r => WizardSeedRowStore.Int(r, PlatformConsts.Permissions.Order)))
.DefaultIfEmpty(0).Max() + 1;
Write(code, null, code, order);
// Yetki agaci menu agacini izler: ust menu zincirindeki her seviye (grubun kendisi haric)
// ayni kodlu bir ara yetkidir; rol ekraninda ekran, menude durdugu dalin altinda gorunur.
string? parentName = null;
if (input.CreateMenu)
{
var dbMenus = await repoMenu.GetListAsync();
foreach (var level in input.ResolveMenuParentChain())
{
if (Same(level.Code, groupName))
continue;
var fileLevel = rows.Find(WizardSeedRowStore.PermissionFile, "Name", level.Code);
var foreign = fileLevel != null
? !Same(WizardSeedRowStore.Text(fileLevel, "GroupName"), groupName)
: !dbPermissions.Any(p => Same(p.Name, level.Code)) && await repoPerm.AnyAsync(a => a.Name == level.Code);
// Yetki adi tekildir; baska grubun yetkisi bu grubun agacina baglanamaz.
if (foreign)
continue;
if (IsOwnable(level.Code))
{
// Menu seviyesi varsa gorunen adi ondan alinir; yeni seviyenin dil anahtari
// menu yazilirken kendi koduyla uretilir.
var displayName = dbMenus.FirstOrDefault(m => Same(m.Code, level.Code))?.DisplayName
?? WizardSeedRowStore.Text(rows.Find(WizardSeedRowStore.MenuFile, nameof(Menu.Code), level.Code), nameof(Menu.DisplayName))
?? level.Code;
Write(level.Code, parentName, displayName, NextOrder(level.Code, parentName));
}
parentName = level.Code;
}
}
if (IsOwnable(code))
Write(code, parentName, code, NextOrder(code, parentName));
var childOrder = 0;
foreach (var (suffix, langKey) in WizardSeedRowKeys.ChildPermissions(input))
{

View file

@ -127,7 +127,8 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
Görsel tutan her kolon (fotoğraf, logo, avatar kopyası) `nvarchar(MAX)` + editör `dxImageUpload`;
değer base64 saklanır, sınırlı boy ve `dxImageViewer` kullanılmaz (deploy ikisini de reddeder).
2. **Yeni ekran** → Wizard yolu. `Definitions` altına otomatik yerleştirme yok; modüle ait yeni
bir kök menü oluştur, `Order = max(Order) + 1`.
bir kök menü oluştur, `Order = max(Order) + 1`. Yetki ağacı menü ağacını izler: ekranın okuma
yetkisi menüdeki dalın ara yetkisinin altına yazılır (`lowcode.instructions.md` §0.12 Menü yeri).
3. **Yeni ekran/menü** → yetki sözleşmesi olmadan önerilmez. Menü ve route aynı ekran
sözleşmesini göstermeli.
4. **Kullanıcıya görünen her metin** → dil anahtarı üzerinden, EN + TR birlikte. Koda gömülü