Uygulama İçerisinde Kişiye Has Özellikleri Kullanma

Yapılacaklar listesinde hala kullanıcı bazında bir ayrım bulunmamaktadır.[Authorize] özelliği sayesinde kullanıcı giriş yaptıysa tüm listeyi görebiliri. Bunun ile birlikte giren kullanıcıya göre bu filtreyi genişletmek gerekmekte.

Öncelikle UserManager<Applicationuser>TodoControllera enjekte edin.

Controllers/TodoController.cs

[Authorize]
public class TodoController : Controller
{
    private readonly ITodoItemService _todoItemService;
    private readonly UserManager<ApplicationUser> _userManager;

    public TodoController(ITodoItemService todoItemService,
        UserManager<ApplicationUser> userManager)
    {
        _todoItemService = todoItemService;
        _userManager = userManager;
    }

    // ...
}

Üst taraftaki using cümlesine dikkat edin.

using Microsoft.AspNetCore.Identity;

UserManager sınıfı ASP.NET Core Kimlik'e ait bir sınıftır. Bu sınıf sayesinde kullanıcıya ait bilgileri alabilirsiniz.

public async Task<IActionResult> Index()
{
    var currentUser = await _userManager.GetUserAsync(User);
    if (currentUser == null) return Challenge();

    var todoItems = await _todoItemService.GetIncompleteItemsAsync(currentUser);

    var model = new TodoViewModel()
    {
        Items = todoItems
    };

    return View(model);
}

Aksiyon içerisinden User özelliğini kullanarak UserManager vasıtası ile kullanıcıların özelliklerine erişebilirsiniz.

var currentUser = await _userManager.GetUserAsync(User);

Şimdi sorabilirsiniz:"Madem User objemiz zaten aksiyondan erişilebilir durumda, peki neden UserManager'a çağrı yapmamız gerekiyor". Burada bulunan User objesinin içerisinde çok basit veriler tutulur.UserManager ise bu kullanıcıya ait tim bilgilerin veri tabanından getirilmesini sağlar.

currentUser değeri hiç bir zaman null olmamalıdır. Zaten daha önce [Authorize] ile kontrolörü ile giriş yapılmadan kullanılamayacağını belirtmiştiniz. Fakat yine de eğer kullanıcı giriş yapmadıysa veya her hangi bir şekilde o an bir problem olduysa onu giriş sayfasına yönlendirmek iyi bir pratiktir. Bunun için Challenge() metodunu kullanabilirsiniz.

if (currentUser == null) return Challenge();

Artık ApplicationUser parametresini GetIncompleteItemsAsync'e gönderdiğinize göre, ITodoItemService arayüzünde de değişiklik yapmalısınız.

Services/ITodoItemService.cs

public interface ITodoItemService
{
    Task<IEnumerable<TodoItem>> GetIncompleteItemsAsync(ApplicationUser user);

    // ...
}

Sıradaki işlem veri tabanını güncelleyerek sadece giriş yapan kullanıcıya has verileri getirmektir.

Veri tabanını güncelleme

TodoItem modeline yeni bir özellik ekleyerek kullanıcıların bilgilerinin tutulmasını sağlamalısınız.

public string OwnerId { get; set; }

Tabi şu anda sadece modelde değişiklik yaptınız ve bunu henüz uygulamadınız. Bundan dolayı daha önce yaptığımız gibi göç ettirmeniz gerekmekte. Bunun için terminalde veya komut satırında dotnet ef komutunu kullanarak aşağıdaki işlemi yapın.

dotnet ef migrations add AddItemOwnerId

Bu yeni bir göç oluşturarak bunun adını AddItemOwner verir. Modelde yaptığımız değişiklikler burada da görülebilir.

Eğer SQLite kullanıyorsanız bu göç'ü otomatik yapamazsınız. Bunun için Migration Oluşturma bölümüne bakabilirsiniz. Tekrar dotnet ef komutu ile bu göçü uygulayabilirsiniz.

dotnet ef database update

Servis sınıfını güncelleme

Veri tabanı ve veri tabanı konteksi güncellendi, artık TodoItemService içerisinde bulunan GetIncompleteItemsAsync metodunu değiştirebilir ve Where sorgusu ekleyebilirsiniz.

Services/TodoItemService.cs

public async Task<IEnumerable<TodoItem>> GetIncompleteItemsAsync(ApplicationUser user)
{
    return await _context.Items
        .Where(x => x.IsDone == false && x.OwnerId == user.Id)
        .ToArrayAsync();
}

Yeni bir kullanıcı oluşturur ve giriş yaparsanız, yapılacaklar listesini boş göreceksiniz. Malesef yeni bir yapılacak eklediğinizde de bu değişmeyecek, çünkü yeni yapılacak ekleme olayının içerisinde kullanıcı bilgilerini kaydetme işlemini yapmanız henüz.

Yeni Yapılacak Olayı Güncellemesi ve Tamamlandı Operasyonu

UserManager kullanarak giriş yapmış kullanıcının bilgilerini AddItem ve MarkDone aksiyonları içerisine paslayabilirsiniz. Bunu daha önce Index aksiyonunda yapmıştınız. Buradaki tek fark bu metodların kullanıcıyı eğer giriş yapmamışsa giriş ekranına yönlendirmek yerine 401 Unauthorized döndürmesidir.

TodoController içerisini aşağıdaki gibi güncelleyin.

public async Task<IActionResult> AddItem(NewTodoItem newItem)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var currentUser = await _userManager.GetUserAsync(User);
    if (currentUser == null) return Unauthorized();

    var successful = await _todoItemService.AddItemAsync(newItem, currentUser);
    if (!successful)
    {
        return BadRequest(new { error = "Could not add item." });
    }

    return Ok();
}

public async Task<IActionResult> MarkDone(Guid id)
{
    if (id == Guid.Empty) return BadRequest();

    var currentUser = await _userManager.GetUserAsync(User);
    if (currentUser == null) return Unauthorized();

    var successful = await _todoItemService.MarkDoneAsync(id, currentUser);
    if (!successful) return BadRequest();

    return Ok();
}

İki serviste ApplicationUser parametresini kabul etmeli. ITodoItemService içerisini aşağıdaki gibi güncelleyin.

Task<bool> AddItemAsync(NewTodoItem newItem, ApplicationUser user);

Task<bool> MarkDoneAsync(Guid id, ApplicationUser user);

Son olarak TodoItemService içerisinde bulunan servis metodunu güncelleyin. AddItemAsync metodu için Owner özelliğini yeti TodoItem oluştururken ayarlayın.

public async Task<bool> AddItemAsync(NewTodoItem newItem, ApplicationUser user)
{
    var entity = new TodoItem
    {
        Id = Guid.NewGuid(),
        OwnerId = user.Id,
        IsDone = false,
        Title = newItem.Title,
        DueAt = DateTimeOffset.Now.AddDays(3)
    };

    // ...
}

MarkDoneAsync metodu içerisinde kullanıcıyı kontrol etmelisiniz. Böylece sadece yapılacak ID'si ile güncelleme yapılamayacaktır.

public async Task<bool> MarkDoneAsync(Guid id, ApplicationUser user)
{
    var item = await _context.Items
        .Where(x => x.Id == id && x.OwnerId == user.Id)
        .SingleOrDefaultAsync();

    // ...
}

Bunu da tamamladık. Bundan sonra her kullanıcı kendi adına yapılacak ekleyebilecek ve başkası bunu göremeyecek veya tamamlandı olarak belirtemeyecek.

results matching ""

    No results matching ""