Tapis.Core.Portal
1.0.2
dotnet add package Tapis.Core.Portal --version 1.0.2
NuGet\Install-Package Tapis.Core.Portal -Version 1.0.2
<PackageReference Include="Tapis.Core.Portal" Version="1.0.2" />
<PackageVersion Include="Tapis.Core.Portal" Version="1.0.2" />
<PackageReference Include="Tapis.Core.Portal" />
paket add Tapis.Core.Portal --version 1.0.2
#r "nuget: Tapis.Core.Portal, 1.0.2"
#:package Tapis.Core.Portal@1.0.2
#addin nuget:?package=Tapis.Core.Portal&version=1.0.2
#tool nuget:?package=Tapis.Core.Portal&version=1.0.2
Tapis.Core.Portal
Müşteri portalı modül paketi (Reminders gibi: tek paket, ürün *.Services + *.Infrastructure projelerinden referanslar; *.Core referans
vermez). Her ürün (HostelManagement, ServiceManagement) bu paketi kendi API'sinde barındırır ve kendi tenant veritabanında kendi tablolarını tutar.
Paket tenant bağlantısı çözmez, CariHesap bilmez, veri okuma uçlarını ve maskelemeyi içermez: ihtiyaç duyduğu her şeyi port üzerinden alır.
İçerik ve yön tablosu
| Klasör | İçerik | Bağımlı olamaz |
|---|---|---|
Entities/ |
MusteriCihaz, MusteriCihazPlatformu, MusteriDogrulamaKaydi, MusteriRizasi |
Services, Ports, Persistence, AspNetCore |
Ports/ |
IPortalVeritabani, PortalVeritabaniOturumu, IPortalMusteriKaynagi, IPortalYerelSaat, IPortalAydinlatmaKaynagi, IPortalBaglam |
Persistence, AspNetCore |
Services/ |
PortalKod, kimlik/rıza/davet çekirdeği, DTO'lar, PortalDavetEpostasi; iç dikiş arayüzleri (internal) |
Persistence, AspNetCore, Microsoft.AspNetCore.*, Microsoft.EntityFrameworkCore.*, Tapis.Core.Infrastructure.* |
Persistence/ |
EF yapılandırmaları, ApplyTapisPortalModel, depolar, IPortalVeritabani sarmalayıcısı (internal) |
AspNetCore |
AspNetCore/ |
PortalToken şeması, çerez, controller tabanları, rıza kapısı, PortalUcDenetimi |
Persistence |
Yön tablosu PortalPaketYuzeyiTests ile imza ve metot gövdesi (IL) taramasıyla doğrulanır. Pakette somut controller yoktur.
Kayıt noktaları
// *.Infrastructure/DependencyInjection.cs (Reminders'ın AddRemindersModule emsali)
services.AddTapisPortal(configuration, o =>
{
o.UrunHarfi = 'H'; // HM 'H', SM 'S' (KALICI)
o.AnahtarBaglami = "hm"; // HM "hm", SM "sm" (KALICI); ilk harf UrunHarfi'nin küçüğü olmak zorunda
o.VarsayilanIssuer = "HostelManagement";
o.VarsayilanAudience = "HostelManagement.Portal";
o.VarsayilanCerezYolu = "/api/hostel/PortalKimlik";
});
services.AddScoped<IPortalVeritabani, UrunPortalVeritabani>();
services.AddSingleton<IPortalYerelSaat, UrunPortalYerelSaat>();
services.AddSingleton<IPortalAydinlatmaKaynagi, UrunAydinlatmaKaynagi>();
// *.HttpAPI/Program.cs
builder.Services.AddTapisPortalAspNetCore(builder.Configuration, builder.Environment);
// DbContext.OnModelCreating (SIRA ZORUNLU)
builder.ApplyConfigurationsFromAssembly(...);
builder.ApplyRemindersModel();
builder.ApplyTapisPortalModel();
if (Database.IsNpgsql()) { builder.ConfigureXminConcurrency(); builder.ConfigureTurkishCaseInsensitive(); }
PortalSecenekleri varsayılansızdır ve kalıcıdır: UrunHarfi + AnahtarBaglami yayımdan sonra değişirse açık oturumlar ve davetler düşer.
Eksik/uyumsuz değer başlangıçta InvalidOperationException; ürün portları kayıtlı değilse uygulama açılmaz.
Port sözleşmesi (güvenlik)
IPortalVeritabani (ihlali tenant karışmasıdır):
TenantIcinAcAsync(tenantId): yalnız bu sürecin uygulaması (Tenancy:UygulamaId) için, tenant'ı Master üzerinden çözer. Çözülemezse (tenant yok, başka uygulama, pasif, bağlantı yok)nulldöner; istisna sızdırmaz. Dönen oturumunTenantId'si istenen tenant olmak zorundadır: paket bunu doğrular, uyuşmazsa oturumu kapatıp reddeder.IstektenAcAsync(): tenant'ı yalnız doğrulanmış principal'inTenantIdclaim'inden veAppIdeşitliğinden alır; header, sorgu dizesi, gövde asla.- İkisi de kurucuda (DI çözülürken) tenant çözmez ve bağlantı açmaz.
- Açılan context denetim interceptor'ı olmadan kurulur (hash/özet işlemleri audit'e girmesin).
- Paket istisnalarda yalnız tür adını loglar (
ex.Messageve tenant DB adı asla); port da bağlantı dizesini mesajına koymamalıdır.
Diğer portlar: IPortalMusteriKaynagi (cari kart okuma, işletme adı, işlem geçmişi izi: kod/telefon/token içermeyen sabit metin; yazılamazsa akış bozulmaz),
IPortalYerelSaat (işletme yerel saati), IPortalAydinlatmaKaynagi (ürüne özgü metin ve varsayılan sürüm; Portal:AydinlatmaSurumu önceliklidir).
PortalDavetIslemleri (IPortalDavetIslemleri) yetkisizdir: yalnız yetkili personel servisleri buna bağımlı olmalıdır (ürün mimari testi). Tenant parametresi yoktur;
koda gömülen tenant IstektenAcAsync oturumunun tenant'ıdır.
Kayıt temizliği (1.0.1)
IPortalKayitTemizligi yetkisizdir ve IPortalDavetIslemleri'nden ayrıdır (o arayüze üye eklemek ürün test sahtelerini kırardı).
Yetki ve çağrı yeri ürünün işidir; ürün mimari testi çağıranları sabitler: SaklamaTemizleAsync(tenantId) yalnız ürünün Provision ucundan
(ClientToken, tenant eşitliği denetlenmiş), KartKayitlariniTemizleAsync(cariHesapId, ...) yalnız yetkili personel servisinden.
SaklamaTemizleAsync: tenantIPortalVeritabani.TenantIcinAcAsyncile açılır. ÇözülemezsePortalSaklamaSonucu.Atlandi == truedöner (başarı değildir: ürün ucu 2xx dışı bir kod dönmelidir). EşiklerTimeProviderUTC'sindenPortal:DavetSaklamaGun(30, en az 7) vePortal:CihazSaklamaGun(90, en az 30) ile hesaplanır; altındaki değer başlangıçta hata verir. İdempotenttir.KartKayitlariniTemizleAsync: tenantIstektenAcAsync'ten gelir; eşik yok. En az bir satır silindiyse işlem geçmişine tek satır yazılır ("Müşteri portalı kayıtları temizlendi: {n} cihaz, {m} davet"; yalnız sayılar). Kartın var olduğunu ve müşteri kartı olduğunu çağıran denetler.KartCihazlariniSilAsync(cariHesapId, cihazIdler, ...)(1.0.2): personelin listede seçtiği cihazlardan yalnız kartın kapanmış cihazları silinir (aynıKartKapaliCihazkriteri DELETE'te de taşınır); aktif cihaz, başka kartın cihazı ve olmayan kimlik atlanır. Davetlere dokunmaz. En az bir satır silindiyse işlem geçmişine tek satır ("Müşteri portalı: seçilen {n} cihaz kaydı silindi"). Liste boyutunu çağıran sınırlar.- Loglar yalnız tenant ve sayıları içerir; hash, ChallengeId, cihaz adı, IP ve cari hesap Id'si yazılmaz.
Tanımlar (tek kaynak: Services/PortalSaklamaKurallari.cs; iki yol için de geçerlidir, OlusturmaTarihi hiçbir kriterde yoktur):
| Kavram | Tanım | Silinir mi |
|---|---|---|
| Açık davet | !Tuketildi && IptalTarihi == null && SonGecerlilik > simdi |
Asla |
| Aktif cihaz | IptalTarihi == null && YenilemeSonGecerlilik > simdi |
Asla |
| Otomatik: eski davet | (Tuketildi && TuketimTarihi < e) \|\| IptalTarihi < e \|\| SonGecerlilik < e (e = şimdi − DavetSaklamaGun) |
Eşikten kesin eskiyse |
| Otomatik: eski cihaz | (IptalTarihi != null && IptalTarihi < e) \|\| (IptalTarihi == null && YenilemeSonGecerlilik < e) (e = şimdi − CihazSaklamaGun) |
Eşikten kesin eskiyse |
| Elle: kartın kapalı daveti | açık olmayan (tüketilmiş, iptal edilmiş ya da süresi dolmuş) | Evet |
| Elle: kartın kapalı cihazı | iptal edilmiş ya da YenilemeSonGecerlilik <= simdi − 5 dk (yenilemeyle yarışmaya karşı pay) |
Evet |
Silme koşulu, yapılandırmadan bağımsız olarak kaydın kapalı olmasını ister: otomatik kriterler eşik karşılaştırmasına ek olarak açık "kapalı" (açık davet / aktif cihaz değil) koşulunu da taşır. Saklama günleri kullanım anında da asgari değerle denetlenir; altındaysa InvalidOperationException fırlar ve hiçbir şey silinmez.
MusteriRizalar (rıza) hiçbir yolda silinmez; İşlem Geçmişi ürünündür. Silme 1000'lik partilerle yapılır: önce partinin Id'leri seçilir,
sonra DELETE kriterin tamamını yeniden taşır (PostgreSQL kriteri satırın güncel hâlinde yeniden denetler; seçimle silme arasında yenilenen,
iptal edilen ya da bağlanan satır silinmez).
Ürün kontrol listesi
PortalSecenekleritüm alanlar; HMH/hm, SMS/sm.ApplyTapisPortalModelsırası:ConfigureXminConcurrency/ConfigureTurkishCaseInsensitive'ten önce.- 3 FK
CariHesaplar(Restrict):MusteriDogrulamaKayitlari,MusteriCihazlar,MusteriRizalar(CariHesapId); paket FK taşımaz. IPortalVeritabanisözleşmesi (yukarıda), audit interceptor'sız.- Maskeleme / allow-list DTO: veri uçları üründe; iç alan sızıntısı reflection testi ürün işi.
- Somut
PortalController/PortalKimlikControlleraynı adlaPortalControllerBase/PortalKimlikControllerBase'ten türer; veri uçlarıPortalControllerBasealtında rıza kapısıyla gelir. Ürün testiPortalUcDenetimi.Dogrula(endpointDataSource)çağırır (hata listesi boş olmalı). - Hız sınırı politikaları ürün kaydeder:
PortalHizSiniri.KimlikPolitikasi/VeriPolitikasi, bölüm anahtarlarıKimlikAnahtari/VeriAnahtari.UseRateLimiter,UseAuthenticationveUseAuthorization'dan SONRA çağrılmalıdır (cihaz bölümü doğrulanmış claim'e bakar). PortalJwt:Keyürüne özgü, ortam değişkeniyle; Master (MasterJwt:Key), tenant (Tenancy:SymmetricKey), istemci (Tenancy:ClientSecret) ve diğer ürünün anahtarından farklı.Portal:CerezYoludar (/api/<ürün>/PortalKimlik); korumalı ortamda başlangıç denetimi zorunlu kılar.- Tek kopya varsayımı: negatif tenant önbelleği süreç içidir (singleton örnek); çok kopyada kopya başına tutulur, güvenlik kararı değildir.
- Gateway'de ürün başına uç listesi (HM
Konaklamalar, SMServisler). Tenancy:UygulamaIdgeçerli Guid.PortalAyarlariPortalbölümü,PortalJwtAyarlariPortalJwtbölümü; paketTenancy:UygulamaId,MasterJwt:*,Tenancy:*anahtar adlarını okur.
Hata kodları ve iletiler
100xx kodları SharedErrorCodes'tan (not bulundu 10001, doğrulama 10009, iş kuralı 10020); pakette yalnız farklılar: PortalHataKodlari.Unauthorized = 10010
(HM değeri, SharedErrorCodes.Unauthorized = 10006'dan farklıdır) ve RizaGerekli = 12050 (portal ortak; ürün enum'ları başka anlamda kullanmaz).
İletiler düz Türkçe sabit (PortalIletileri), yerelleştirme yok.
Bağımlılıklar
Tapis.Core.Shared (2.0.20), Tapis.Core.Verification (>= 1.0.0), EF Core 10.0.10, Npgsql EF 10.0.0, Microsoft.AspNetCore.Authentication.JwtBearer 10.0.10
(public yüzeyde JwtBearer tipi yoktur).
Tapis.Core.Infrastructure'a bağımlılık yoktur; HarfDuyarli anotasyonu (Tapis:HarfDuyarli) pakette tekrarlanır (PortalHarfDuyarli), Infrastructure ile eşitliği testle
kilitlidir (PortalHarfDuyarliTests); host'un ConfigureTurkishCaseInsensitive için Infrastructure >= 1.0.6 kullanması kendi şema kuralıdır. Derlenmiş pakette
Tapis.Core.Infrastructure assembly başvurusu da yoktur (test kilitli).
Hata davranışı ve başlangıç sıkılığı
- Bağlantı ilk sorguda açılır: EF bağlantıyı context oluşunca değil ilk komutta açar, bu yüzden "database tenant_x does not exist" gibi sürücü hataları ilk depo çağrısında
çıkar. Paket bunları yakalar: JWT doğrulamasında
context.Fail(401),Baglan/Yenileyolunda HM'deki genel red kodları (400 / 401),Cikis204; log'da yalnız istisna tür adı. PortalJwt:Issuer/AudiencedoluysaPortalSecenekleri.VarsayilanIssuer/VarsayilanAudienceile aynı olmak zorundadır (başlangıç hatası).PortalKodkurucusu ürün harfi ile bağlam eşleşmesiniPortalSecenekleri.Dogrulaile aynı kuralla doğrular.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 10.0.10)
- Microsoft.EntityFrameworkCore (>= 10.0.10)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.10)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 10.0.0)
- Tapis.Core.Shared (>= 2.0.20)
- Tapis.Core.Verification (>= 1.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
1.0.2: secili cihaz silme (eklemeli): IPortalKayitTemizligi.KartCihazlariniSilAsync; listeden secilen cihazlardan yalniz kartin kapanmis (iptal/suresi dolmus) cihazlari silinir, aktif cihaz silinmez, davetlere dokunulmaz; islem gecmisine yalniz sayi. Sema degismez. 1.0.1: portal kayit temizligi (eklemeli): IPortalKayitTemizligi (SaklamaTemizleAsync otomatik saklama, KartKayitlariniTemizleAsync elle temizlik; yetkisiz), PortalSaklamaSonucu, Portal:DavetSaklamaGun (30, en az 7) ve Portal:CihazSaklamaGun (90, en az 30). Acik davet, aktif cihaz ve riza kayitlari silinmez. Sema degismez. 1.0.0: ilk surum. Musteri portali modulu (HostelManagement portal cekirdeginin paketlenmis hali): MusteriCihaz/MusteriDogrulamaKaydi/MusteriRizasi entity'leri ve ApplyTapisPortalModel, HMAC etiketli davet kodu (PortalKod, urun harfi + HKDF baglami), kimlik/riza/davet cekirdegi, PortalToken JWT semasi ve Portal policy, HttpOnly cerez, controller taban siniflari ve riza kapisi filtresi, PortalUcDenetimi. Urun IPortalVeritabani, IPortalMusteriKaynagi, IPortalYerelSaat, IPortalAydinlatmaKaynagi saglar. Kalici sabitler (HM: H + hm) hicbir surumde degismez.