Получите данные Lavavel (5) без прямой связи - PullRequest
0 голосов
/ 25 октября 2018

У меня есть приложение, состоящее из этих таблиц

  • пользователей
  • каналов (с user_id внешним ключом для пользователя)
  • списков воспроизведения (с user_idвнешний ключ для пользователя и внешний channel_id для каналов)
  • дорожки (с playlist_id внешним ключом для списков воспроизведения, НО НЕ user_id внешний ключ)

User модельопределяется с помощью:

public function channels()
{
    return $this->hasMany('App\Channel');
}

Channel модель определяется с помощью:

public function playlists()
{
    return $this->hasMany('App\Playlist');
}

$this->belongsTo('App\User'))

Playlist модель определяется с:

public function tracks()
{
    return $this->hasMany('App\Track');
}

$this->belongsTo('App\Channel'))

Track модель определяется с помощью:

public function playlist()
{
   return $this->belongsTo('App\Playlist');
}

Теперь при перечислении треков в конкретном списке воспроизведения Iсделать это:

function list($playlist) {
    $tracks = Track::with('playlist')->get();
    return response()->json($tracks);
}

Это правильно работает на странице http://.../tracks/2 (где 2 - идентификатор списка воспроизведения), но если пользователь изменит 2 на 3, он потенциально может увидеть дорожки в списке воспроизведения # 3, которые могутне будь его.Итак, как мне получить идентификатор пользователя из списка воспроизведения, чтобы показать только дорожки, принадлежащие списку воспроизведения, который фактически есть у пользователя?

1 Ответ

0 голосов
/ 25 октября 2018

В вашем коде похоже, что вы на самом деле не загружаете плейлист, указанный в вашем URL-адресе.$playlist здесь должно быть 2 с вашим примером URL (http://.../tracks/2):

function list($playlist) {
    $tracks = Track::with('playlist')->get();
    return response()->json($tracks);
}

Вы просто загружаете все дорожки во всей вашей системе, стремясь загрузить ихсоответствующие Playlist объекты.

Предполагая, что с этим URL вы хотите показать дорожки для плейлиста 2, если и только если он принадлежит аутентифицированному пользователю, что вы должны сделать, это найтисписок воспроизведения по его идентификатору, авторизуйте, что Playlist принадлежит вошедшему в систему пользователю, а затем загрузите его tracks, используя соотношение:

public function list($id)
{
    // Find a playlist with the given ID, or 404 if none could be found.
    $playlist = Playlist::findOrFail($id);

    // If the playlist does not belong to the user, throw an AuthorizationException.
    if ($playlist->user_id != auth()->user()->id) {
        throw new AuthorizationException();
    }

    // Return a response, passing through the tracks belonging to the playlist.
    return response()->json($playlist->tracks);
}

Лучшим способом обработки авторизации будет использование Встроенные функции авторизации Laravel , в первую очередь политики .Это позволит вам отделить логику авторизации от контроллера и сохранить всю логику авторизации в одном и том же / похожем месте:

  • Создайте политику, используя php artisan make:policy PlaylistPolicy, которая создаст класс App\Policies\PlaylistPolicy.
  • В этой политике просто определите метод, который обозначает действие, которое вы авторизуете для своих плейлистов.В этом примере вы подтверждаете, может ли пользователь просматривать данный список воспроизведения, поэтому view будет моим предложением имени метода здесь.
  • Этот метод будетпринять 2 параметра, аутентифицированного пользователя и интересующий вас объект Playlist:

    public function view(User $user, Playlist $playlist)
    {
        //
    }
    
  • В этом методе все, что вам нужно сделать, это добавить некоторую логику, которая определяетесли данный пользователь (вошедший в систему пользователь) имеет доступ к просмотру данного Playlist.Метод должен возвращать true, если у пользователя есть доступ, или false, если нет.

    public function view(User $user, Playlist $playlist)
    {
        return $user->id === $playlist->user_id;
    }
    
  • Теперь вам просто нужно зарегистрировать политику в вашем App\Providers\AuthServiceProvider.Вам просто нужно сопоставить модель Playlist с PlaylistPolicy, добавив к свойству $policies, и все будет хорошо.

    protected $policies = [
        Playlist::class => PlaylistPolicy::class
    ];
    
  • Теперь вместо этогоВыражение if в вашем контроллере вы можете просто использовать метод authorize, который должен присутствовать в вашем контроллере (если признак AuthorizesRequests равен use d).

    public function list($id)
    {
        $playlist = Playlist::findOrFail($id);
    
        $this->authorize('view', $playlist);
    
        return response()->json($playlist->tracks);
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...