Asp.NET Core Identity – RoleManager Sınıfı İle Rol Yönetimi – XIV

Merhaba,

Asp.NET Core Identity yazı dizimizin 14. makalesinde, uygulamamızda kullanıcıları belirli yetkiler doğrultusunda yönlendirebilmek ve sayfa odaklı erişim durumlarına müdahale edebilmek için rol yönetimi üzerine konuşacağız.

Rol Bazlı Yetkilendirme Nedir? Roles Based Authorization

Rol bazlı yetkilendirme, yukarıdaki giriş cümlesinde de ifade etmeye çalıştığım gibi kullanıcıların belli başlı sayfalara erişimini belirlememizi sağlayan ve bunun için roller tanımlayarak yetkilendirme yapmamıza imkan tanıyan bir stratejidir.

Şöyle basit bir örnekle metafor yaparsak eğer; ilaç almaya gittiğiniz eczanenin arka odasının kapısında “Personel Harici Giremez!” uyarısı görmüşsünüzdür. Ha işte, o odaya erişebilmek için o eczanede “Personel” rolüne sahip olmanız gerekmektedir. Eğer ki dışarıdan gelen müşteri iseniz ne yazık ki o odaya giremezsiniz.

Web uygulamalarında da benzer mantık geçerlidir ve kullanıcılara rol odaklı sayfa erişimleri sağlanmaktadır. Örneğin; Maliye bakanlığının otomasyonunda “Bütçe” sayfasına sade ve sadece “Director” ya da “Manager” rolüne sahip olan kullanıcılar erişebilirken, “Şehirler” sayfasına herkes erişebilmektedir.

RoleManager Sınıfı

Asp.NET Core Identity mekanizmasında uygulamaya dair tüm rol yönetimini RoleManager sınıfı üstlenmektedir. Rol ekleme, silme, güncelleme ve listeleme sorumluluklarını gerçekleştirmektedir.

IdentityRole Sınıfı İle Rol Entitysi Tanımlama

Uygulamada bir rol entitysi tanımlayabilmek için ilgili sınıfın “IdentityRole” sınıfından türemesi gerekmektedir.

    public class AppRole : IdentityRole<int>
    {
        public DateTime OlusturulmaTarihi { get; set; }
    }

Ve bu rol sınıfı uygulamadaki Context nesnesinin “IdentityDbContext” base classına aşağıdaki gibi bildirilmesi gerekmektedir.

    public class AppDbContext : IdentityDbContext<AppUser, AppRole, int>
    {
        public AppDbContext(DbContextOptions<AppDbContext> dbContext) : base(dbContext) { }
    }

Ayrıca yine ilgili sınıfın Startup dosyasında da AddIdentity fonksiyonu ile aşağıdaki gibi belirtilmesi gerekmektedir.

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentity<AppUser, AppRole>(_ =>
            {
                .
                .
                .
            }
        }
Rol Oluşturma

Rol oluşturabilmek için RoleManager sınıfının “Create” metodunu aşağıdaki gibi kullanabiliriz.

    public class RoleController : Controller
    {
        readonly RoleManager<AppRole> _roleManager;
        public RoleController(RoleManager<AppRole> roleManager)
        {
            _roleManager = roleManager;
        }
        .
        .
        .
        [HttpPost]
        public async Task<IActionResult> CreateRole(RoleViewModel model)
        {
            IdentityResult result = await _roleManager.CreateAsync(new AppRole { Name = model.Name, OlusturulmaTarihi = DateTime.Now });
            if (result.Succeeded)
            {
                //Başarılı...
            }
            return View();
        }
    }
Rol Güncelleme

Oluşturulmuş rolü güncelleyebilmek için 16. satırda olduğu gibi “Update” metodunu kullanabiliriz.

    public class RoleController : Controller
    {
        readonly RoleManager<AppRole> _roleManager;
        public RoleController(RoleManager<AppRole> roleManager)
        {
            _roleManager = roleManager;
        }
        [HttpPost]
        public async Task<IActionResult> CreateRole(RoleViewModel model, string id)
        {
            IdentityResult result = null;
            if (id != null)
            {
                AppRole role = await _roleManager.FindByIdAsync(id);
                role.Name = model.Name;
                result = await _roleManager.UpdateAsync(role);
            }
            else
                result = await _roleManager.CreateAsync(new AppRole { Name = model.Name, OlusturulmaTarihi = DateTime.Now });

            if (result.Succeeded)
            {
                //Başarılı...
            }
            return View();
        }
    }
Rol Silme

Rol silmek istediğimizde ise Delete fonksiyonunu aşağıdaki gibi kullanmamız yeterlidir.

    public class RoleController : Controller
    {
        readonly RoleManager<AppRole> _roleManager;
        public RoleController(RoleManager<AppRole> roleManager)
        {
            _roleManager = roleManager;
        }
        .
        .
        .
        public async Task<IActionResult> DeleteRole(string id)
        {
            AppRole role = await _roleManager.FindByIdAsync(id);
            IdentityResult result = await _roleManager.DeleteAsync(role);
            if (result.Succeeded)
            {
                //Başarılı...
            }
            return RedirectToAction("Index");
        }
    }
Rolleri Listeleme

Tüm rolleri elde etmek ve listeleyebilmek için direkt olarak RoleManager nesnesinin Roles propertysini kullanabilirsiniz.

        public IActionResult Index()
        {
            return View(_roleManager.Roles.ToList());
        }
Kullanıcılara Rol Atama

Tanımlanmış rolleri uygulamadaki kullanıcılara atayarak bir nevi kullanıcı yetkilendirme işlemini gerçekleştirebilmek için UserManager nesnesinin AddToRole metodu kullanılmaktadır.

        public async Task<IActionResult> RoleAssign(string id)
        {
            AppUser user = await _userManager.FindByIdAsync(id);

            await _userManager.AddToRoleAsync(user, "Administrator");
            await _userManager.AddToRoleAsync(user, "Moderator");
            await _userManager.AddToRoleAsync(user, "Editor");
            await _userManager.AddToRoleAsync(user, "tor");
            return View();
        }

Burada dikkat edilmesi gereken husus her bir rolün önceden tanımlanmış olması gerekmektedir. Aksi taktirde hatayla karşılanacaktır.

Rol atamayı daha işlevsel olarak nasıl yapabiliriz? sorusunu sorduğunuzu duyar gibiyim…
Evet, sanırım uygulamada tanımlanmış/tanımlanacak rolleri yukarıdaki gibi statik olarak önceden tahmin etmenizi beklemek ve daha da tuhafı bu tanımlamaları tüm kullanıcılar için gerçekleştirmek yersiz olacaktır… Muhtemeldir ki sizde hak vereceksiniz buradaki en doğru aksiyon rol atamak istediğimiz kullanıcıya tıkladığımız zaman tüm rollerin listelenmesi ve hatta bu listede ilgili kullanıcıyla ilişkilendirilmiş önceki rollerin seçili gelmesi ve aralarından seçtiklerimizin ilgili kullanıcıyla ilişkilendirilmesi olacaktır.

Bunun için herşeyden önce hangi rolün seçildiğine dair bilgi taşıyacak olan ViewModeli geliştirmek gerekmektedir…

    public class RoleAssignViewModel
    {
        public int RoleId { get; set; }
        public string RoleName { get; set; }
        public bool HasAssign { get; set; }
    }

Yukarıdaki viewmodeli incelerseniz eğer role dair id ve name değerlerini tutmakla birlikte o anki rolün ilgili kullanıcıya atanıp atanmadığı bilgisini de(HasAssign) tutmaktadır. Şimdi yapmamız gereken kullanıcıya rol ekleme sayfası oluşturarak, tüm rolleri orada seçilebilir bir şekilde listelemek ve biryandan da kullanıcıyla ilişkili rol varsa işaretli bir şekilde getirmektir. Akabinde seçilen tüm rolleri kullanıcıyla ilişkilendirerek atama işlemini sonlandıracağız.

    public class RoleController : Controller
    {
        readonly RoleManager<AppRole> _roleManager;
        readonly UserManager<AppUser> _userManager;
        public RoleController(RoleManager<AppRole> roleManager, UserManager<AppUser> userManager)
        {
            _roleManager = roleManager;
            _userManager = userManager;
        }
        public async Task<IActionResult> RoleAssign(string id)
        {
            AppUser user = await _userManager.FindByIdAsync(id);
            List<AppRole> allRoles = _roleManager.Roles.ToList();
            List<string> userRoles = await _userManager.GetRolesAsync(user) as List<string>;
            List<RoleAssignViewModel> assignRoles = new List<RoleAssignViewModel>();
            allRoles.ForEach(role => assignRoles.Add(new RoleAssignViewModel
            {
                HasAssign = userRoles.Contains(role.Name),
                RoleId = role.Id,
                RoleName = role.Name
            }));

            return View(assignRoles);
        }
        [HttpPost]
        public async Task<ActionResult> RoleAssign(List<RoleAssignViewModel> modelList, string id)
        {
            AppUser user = await _userManager.FindByIdAsync(id);
            foreach (RoleAssignViewModel role in modelList)
            {
                if (role.HasAssign)
                    await _userManager.AddToRoleAsync(user, role.RoleName);
                else
                    await _userManager.RemoveFromRoleAsync(user, role.RoleName);
            }
            return RedirectToAction("Index", "User");
        }
    .
    .
    .
    //diğer actionlar
    .
    .
    .
    }

Yukarıdaki kod bloğunu incelerseniz eğer; 13. satırda uygulamadaki tüm rolleri, 14. satırda ise o an yetki atanacak olan kullanıcının mevcut tüm rollerini elde edip ardından bu bilgileri bir adım önce oluşturduğumuz “RoleAssignViewModel” isimli viewmodel nesnelerine atayarak view’e gönderiyoruz. Kullanıcıya dair view’de yapılan seçim neticesinde eklenen roller 32. satırda olduğu gibi “AddToRoleAsync” metodu ile kullanıcıyla ilişkilendiriliyor yahut alınan yetkiler ise 34. satırda “RemoveFromRoleAsync” metoduyla kullanıcıdan siliniyor. İlgili view kaynağınıda görmek isterseniz aşağıdaki kod bloğunu inceleyebilirsiniz.

@model List<AspNetCoreIdentityExample.Models.ViewModels.RoleAssignViewModel>
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<h1>Role Assign</h1>
<form asp-action="RoleAssign" asp-controller="Role">
    <table class="table">
        <thead>
            <tr>
                <th>
                </th>
                <th>
                    Role Name
                </th>
            </tr>
        </thead>
        <tbody>
            @for (int i = 0; i < Model.Count; i++)
            {
                <tr>
                    <td><input type="checkbox" asp-for="@Model[i].HasAssign" /> </td>
                    <td>
                        @Model[i].RoleName
                        <input type="hidden" asp-for="@Model[i].RoleId" />
                        <input type="hidden" asp-for="@Model[i].RoleName" />
                    </td>
                </tr>
            }
            <tr>
                <td colspan="2">
                    <button>Rol Ata</button>
                </td>
            </tr>
        </tbody>
    </table>

</form>

Asp.NET Core Identity - RoleManager Sınıfı İle Rol Yönetimi - XIV

Bu noktadan itibaren bir sonraki içeriğimizde sayfa yetkilendirme(authorization) işlemini ele alacağız.

O halde şimdilik görüşmek üzere diyelim…

İlgilenenlerin faydalanması dileğiyle…
İyi çalışmalar…

Not : Örnek projeyi indirmek için buraya tıklayınız.

Bunlar da hoşunuza gidebilir...

2 Cevaplar

  1. 25 Eylül 2019

    […] Asp.NET Core Identity – RoleManager Sınıfı İle Rol Yönetimi – XIV […]

  2. 02 Ekim 2019

    […] önceki RoleManager Sınıfı İle Rol Yönetimi başlıklı makalemizde uygulama bazlı rol yönetimini incelemiş bulunmaktayız. Bu […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir