Photo by Danielle Rice on Unsplash

Permission, Package And Feature Management With AspNetCore

Farklı domainlerde farklı amaçlara hizmet eden binlerce SaaS uygulama artık hayatımızın merkezi haline geldi. Tam bu noktada uygulamaların hepsinde ortak olan ancak her uygulamanın farklı kombinasyonlarla çözmeye çalıştığı temel bir problem var. Bu yazıda bu problemi ortak bir noktadan nasıl çözebileceğimize odaklanırken bu problem için geliştirdiğim bir paketi sizlerle tanıştıracağım.

Yazının başlığı bu problemi özetliyor. Problemimiz, uygulamalarda sıkça gördüğümüz Permission , Package ve Feature kavramları ve bu kavramların yönetimi.

Farklı başlıklara sahip problemleri ortak bir çözüme kavuştururken dikkat etmemiz gereken ilk nokta, bu başlıklar altında bulunan Use-Case senaryolarını özetlemek ve bir benzerlik yakalamak olacaktır.

Permission yani izin kavramı oldukça sık karşılaştığımız bir senaryo. Herhangi bir modül veya sistem üzerinde yer alan herhangi bir endpointi kullanmak için kullanıcının gerekli izine sahip olup olmaması olarak özetleyebileceğimiz bu kavram bize Authorization konusunu hatırlatıyor.

Authorization genellikle Role-Based bir yapıda kurgulanıyor. Uygulamayı geliştiren ekip belirli roller oluşturarak ilgili operasyonlardan önce kullanıcı bu role sahip mi sorusunu soracak mekanizmaları geliştiriyor ve Authorization sağlanmış oluyor. Ancak bahsettiğim bu model ilkel bir yöntem haline geldi. Son zamanlarda SaaS uygulamalarda gördüğümüz Authorizationyapıları, daha dinamik bir şekilde bu kontrolleri yapabilmemizi sağlarken ek olarak bu operasyonun kullanıcıya devredilmesi standart haline geldi.

Yani sistem içerisinde gerçekleşen her olay için bir Permission ayarlanabiliyor. Özellikle Multi Tenant yapılarda karşımıza çıkan bu yapı sayesinde kullanıcı default izinlere sahip bir şekilde hayatına başlıyor. Tenant’ı manage eden kişi istediği kişiye istediği izini vererek kullanıcının yetki sınırlarını genişletebiliyor veya daraltabiliyor.

Her iki senaryoda da ortak olan tek kısım, kullanıcının veya isteği identify ettiğimiz yapının ilgili key değerine sahip olup olmamasına göre şekilleniyor.

Package veya Subscription her SaaS uygulamada karşımıza çıkan bir case.

Bir satın alma işleminden sonra uygulama içerisinde bazı modüllerin açılıp/kapanması olarak özetleyebileceğimiz bu senaryoda da ortak bir nokta var.
Paketlerin içerisinde bazı limitler ve izinler mevcut. Permission yapısından tek farkı izinlerin veya limitlerin bir grup halinde fiyatlandırılmasıdır.
Kullanıcının veya isteği identify ettiğimiz yapının paketine bakılarak operasyon devam eder veya Paket Yükseltme mesajları ile kullanıcı karşı karşıya bırakılır. Aslında yine bir key değerine sahip olup olmamasına göre senaryolar oluşturuluyor diyebiliriz.

Feature Management veya Feature Flag olarak tanıdığımız yapılar SaaS uygulamalarda oldukça kullanışlı yapılar ortaya çıkarmamızı sağlıyor.

Yeni geliştirilen özellikler veya paketten bağımsız satın alınması gereken add-ons olabilir. Bu senaryolarda genellikle bir flag belirleniyor ve işlem gerçekleşirken bu değer kontrol ediliyor. Bu flag değerine sahip olan istekler hayatına devam ederken sahip olmayan istekler yarıda kesiliyor veya kullanıcıya hiç gösterilmiyor. Ortak noktamız yine key kontrolünden ibaret.

Tüm bu senaryoları tek bir çözüm kümesine nasıl kavuşturacağımız artık yavaş yavaş kafamızda şekilleniyor. Dinamik key kontrolü yapan bir yapı geliştirmemiz gerekiyor. Dinamik çözümler geliştirirken en önemli olan konulardan birbirinden farklı senaryolarda da geliştirilen çözümün sorunsuz çalışmasıdır.

Belirlediğimiz senaryolarda hayal edemediğimiz kısım key kontrolünün hangi yapı üzerinde sağlanacağıdır. Bazı sistemlerde paketler, izinler veya feature flag’ler user üzerine tanımlanırken bazı sistemlerde domaine göre farklı yapılar üzerine tanımlanabiliyor. Bir e-ticaret uygulamasını düşünelim. Ürünlerimizi satmak için sisteme kayıt oluyoruz ve mağazalar oluşturuyoruz.
Ürün sayısı, fotoğraf sayısı gibi özellikler paket şeklinde tanımlanıyor. Ancak bu paketler satıcı üyeliğine değil açtığımız mağazalar üzerine tanımlanıyor. Satıcı üyeliğimiz içerisinde 3 farklı mağazamız olduğunu düşünürsek o zaman bizim için user bilgisinin hiçbir önemi yok. Kullanıcının işlem yapmak istediği mağaza üzerinde tanımlı bilgileri kontrol etmemiz gerekiyor.

Sorunlarımızı da belirlediğimize göre artık çözüme geçebiliriz.

Bu kontrolleri yaparken isteği çözüp anlamlandıracağımız kısımlara Identifier diyeceğiz. Sistem içerisinde birden fazla Identifier olabilir. Identifier bize kontrolü hangi parametre üzerinde yapacağımızı bildirmek zorundadır. Örneğin User üzerinde kontrolleri yapacaksak tanımlanan Identifier UserId bilgisini geri döndürmelidir. E-ticaret örneğini canlandırırsak tanımlanan Identifier StoreId bilgisini geri döndürmelidir.
Böylece operasyonlardan önce bu isteği yapabilmesi için gerekli olan permission veya diğer kavramları bu bilgiler doğrultusunda kontrol edeceğiz.

Makalenin geri kalanında sistem içerisinde işlem yapan kullanıcının tanımlanan izinlere sahip olup olmadığını kontrol eden bir örneği gerçekleştirerek devam edeceğim.

Permission kontrolleri yapılırken User üzerinden bir identify operasyonu gerçekleşeceği için o esnada güncel User bilgisine erişebileceğimiz bir Identifier belirleyerek işe başlıyoruz.

UserIdentifier.cs

Bu örnekte benim için User bilgisi request üzerinde bulunan id bilgisi olduğu için HttpContext üzerinden bu bilgiyi return ediyorum. İsteğe göre veri tabanı üzerinden veya farklı servisler üzerinden bu bilgi elde edilebilir.

Örneğimizi biraz daha geliştirelim. Tek bir identifier yerine iki farklı identifier kullanalım.

OrganizationIdentifier.cs

Bu identify yapısında da fake bir method üzerinden sanki veri tabanından bir kayıt çekiyormuş gibi olay örgüsünü tamamladık.

Tespit yöntemlerini tamamladığımıza göre artık ikinci adıma geçebiliriz.

Permissionların tanımlanması ve kolay bir şekilde yönetilebilmesi için basit bir context oluşturdum.

DefinationContext üzerine gereken tüm izinleri provider seviyesinde tanımlayarak check senaryolarında provider ve permission ikilisini kontrol edebileceğimiz bir context oluşturmuş olduk.

Artık tek yapmak gereken istediğimiz noktada bu kontrolü gerçekleştirmek.

Bir controller içinde bulunan basit bir endpoint. EasyCheck isimli bir attribute ile bu endpointi permission seviyesinde koruma altına aldım. Bu endpoint çağırıldığında güncel User bilgisi geliştirdiğimiz Identifier üzerinden bulunarak lead.read anahtar kelimesi ile kontrol edilecek. Eğer şartlar sağlanmıyorsa action durdurulup hayat sona erecek.

Farklı sağlayıcılar üzerinden farklı anahtar kelimeleri kontrol eden küçük bir yapı geliştirmiş olduk. Evet farkındayım çok fazla kod var. Endişelenme, senin için bu yapıyı küçük bir kütüphaneye dönüştürdüm. Bu yazıda olmayan ayrıntılı senaryoları, manuel check yöntemlerini, izinlerin contextler üzerine nasıl tanımlanacağını, izinlerin ilgili contextler üzerinden nasıl kaldırılacağını ve bu süreçleri şimdilik PostgreSQL üzerinde nasıl yöneteceğini aşağıdaki linkten öğrenebilirsin.

EasyPermissionManagement oldukça genç ve toy bir kütüphane, farklı senaryolarla karşılaştıkça olgunlaşacak ve daha iyi bir hale gelecektir. Geri bildirim için issue açabilirsin.

Yazdığınız kodlar production ortamında hatasız koşsun, testler sizi korusun.

--

--

Medium independent DevOps publication. Join thousands of aspiring developers and DevOps enthusiasts

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Furkan Güngör

Furkan Güngör

Solution Developer — I want to change the world, give me the source code.