Laravel Türkiye Discord Kanalı Forumda kod paylaşılırken dikkat edilmesi gerekenler!Birlikte proje geliştirmek ister misiniz?

Merhabalar,

Öncesinde araştırdığım fakat best practice denilen yolunu bulamadığım bir konu ile karşınızdayım.


User:
	- id
	- name
	- role_id
Role:
	- id 
	- name
Post:
	- id 
	- user_id
	- title
	- content
	- slug
	- is_active

Yukarıda model şemasını verdim. Rol olarak admin, editor ve fixer olduğunu varsayalım.

Kullanılan Sınıflar:

  • PostController
  • UpdatePostRequest

Case:
Tek bir endpoint üzerinden, bir posta ait update işlemi yapılmalıdır. Bu endpointe admin veya editor girer (IDOR zaafiyetini göz ardı etmenizi bekleniyorum), güncellemesini yapar ve çıkar.

Post model için:
admin:
- Tüm kayıtlara ve tüm alanlara yetkisi var.
editor:
- Sadece kendi kayıtlara yetkisi var.
- Kendi kayıtlarında, is_active sütunu haricindekilere yetkisi var.
fixer:
- Tüm kayıtlara yetkisi var.
- Tüm kayıtlarda, slug ve is_active sütunlarına yetkisi var.


Kullanılan sınıflarla bu case nasıl çözebilirsiniz?
Eğer bu sınıfları kullanmak yerine best practice olarak gördüğünüz farklı çözüm önerileri varsa benimle paylaşabilir misiniz?

Not: Okuduğunuz metin veya dokümantasyonda paylaşabilirseniz sevinirim.

    mgsmus Senaryoya göre örnekleyebilir misiniz? Dokümantasyon, belirtilen case özelinde kararlı bir açıklama sunmuyor.

    Repository Pattern ve Route Model Bind işlemi olmadan örnekleyebilir misiniz?

      debiyach Repository pattern zaten yok. Model binding kullanmadığınızda ise bir yerde Post::findOrFail($id) gibi modeli buluyorsunuz demektir:

      $post = Post::findOrFail($id);
      
      if ($request->user()->cannot('update', $post)) {
          abort(403);
      }
      
      // ya da
      
      if (!Gate::allows('update-post', $post)) {
          abort(403);
      }

        mgsmus Case üzerinde üç farklı rol var. Üçünün de güncelleme yetkisi var. İlettiğiniz kod parçacığında, bütün roller tüm sütunlara update atabilir. Fakat case üzerindeki durum biraz farklı, rol bazlı sütunlara yetki durumu söz konusu.


        Post model için:
        admin:
        - Tüm kayıtlara ve tüm alanlara yetkisi var.
        editor:
        - Sadece kendi kayıtlara yetkisi var.
        - Kendi kayıtlarında, is_active sütunu haricindekilere yetkisi var.
        fixer:
        - Tüm kayıtlara yetkisi var.
        - Tüm kayıtlarda, slug ve is_active sütunlarına yetkisi var.

          debiyach Mesela Gate kullandınız:

          Gate::define('update-post', function (User $user, Post $post) {
              // Kullanıcı admin veya fixer ise güncelleme yetkileri var. Sadece fixer slug ve 
              // is_active alanlarını değiştirme yetkisi var. Bunu gate dışında yapacağız.
              if($user->isAdmin() || $user->isFixer()) {
                  return true;
              }
          
              // Kullanıcı editör ise sadece kendine ait olan ve is_active true olan kayıtları
              // düzenleme yetkisine sahip.
              if($user->isEditor()) {
                  return $user->id === $post->user_id 
                      && $post->is_active === true;
              }
          
              return false;
          });

          PostController::update():

          public function update(UpdatePostRequest $request, $id)
          {
              $post = Post::findOrFail($id);
          
              // Şartlara uymazsa 403 dönecek...
              Gate::authorize('update-post', $post);
          
              $data = $request->validated();
          
              // Kullanıcı fixer ise sadece izin verilen ayarları güncellemesini sağlayacağız.
              if($user->isFixer()) {
                  $data = Arr::only($data, ['slug', 'is_active']);
              }
          
             $post->update($data);
          
              // ...
          }

          Fixer için UpdatePostRequest içinde ayrı bir rules dizisi de oluşturabilirsiniz:

          public function rules(): array
          {
              // Standart kurallar.
              $rules = [
                  'title' => 'required|unique:posts|max:255',
                  'body' => 'required',
                  'slug' => 'string',
              ];
              
              // Kullanıcı admin ise ayrıca is_active verebilir.
              if ($this->user()->isAdmin()) {
                  $rules['is_active'] = 'boolean';
              }
          
              // Fixer sadece is_active ve slug alanlarını güncelleyebilir.
              if ($this->user()->isFixer()) {
                  $rules = [
                      'is_active' => 'boolean',
                      'slug' => 'string',
                  ];
              }
          
              return $rules;
          }
          public function update(UpdatePostRequest $request, $id)
          {
              $post = Post::findOrFail($id);
          
              Gate::authorize('update-post', $post);
          
              $post->update($request->validated());
          
              // ...
          }

            mgsmus Öncelikle kodunuz gayet güzel ve anlaşılır olmuş. Elinize sağlık. Örneklemenizi istediğim kısım;

            • fixer, slug ve is_active alanlarına müdahele edebilir.
            • editor, sadece kendi kayıtlarına müdahele edebilir.

            O zaman şu şekilde revize etmemiz gerekiyor.

            Gate::define('update-post', function (User $user, Post $post) {
                // Kullanıcı admin veya fixer ise güncelleme yetkileri var. Sadece fixer slug ve 
                // is_active alanlarını değiştirme yetkisi var. Bunu gate dışında yapacağız.
                if($user->isAdmin() || $user->isFixer()) {
                    return true;
                }
            
                // Kullanıcı editör ise sadece kendine ait olan kayıtları düzenleme yetkisine sahip.
                if($user->isEditor()) {
                    return $user->id === $post->user_id;
                }
            
                return false;
            });

            PostController::update():

            public function update(UpdatePostRequest $request, $id)
            {
                $post = Post::findOrFail($id);
            
                // Şartlara uymazsa 403 dönecek...
                Gate::authorize('update-post', $post);
            
                $data = $request->validated();
            
                // Kullanıcı fixer ise sadece izin verilen ayarları güncellemesini sağlayacağız.
                if($user->isFixer()) {
                    $data = Arr::only($data, ['slug', 'is_active']);
                }
            
                if($user->isEditor()) {
                    $data = Arr::only($data, ['title', 'content']);
                }
            
               $post->update($data);
            
                // ...
            }

            Model üzerindeki fillable dizisinde rol bazında değişiklik yapıp, create etmemiz daha sağlıklı olmaz mı?
            Yukarıdaki yazdığınız yapıyı refactor edecek olsanız nasıl bir yapı kurardınız?

            public function store(Request $request)
            {
            
              $postModel = new Post();
              $postModel->create($postModel->getFillable());
            
            }