Имею следующую схему данных
Users
. Таблица с данными пользователейJournals
. Таблица со списком журналов.Entries
. Таблица со списком записей в журналах.journal_user
. Журнал могут вести разные пользователи. Таблица описывает права. Только те пользователи, которым указаны в этой таблице для определённого журнала, могут его вести.Users
к Entries
. Каждая запись в журнале принадлежит определённому пользователю.Есть Journal
, который могут заполнять Entries
определённые Users
. Каждая Entry
принадлежит определённому User
. И только пользователь, который сделал эту Entry
может её редактировать. Имеется необходимость в следующих ограничениях:
Journal
только определённые Users
могут оставлять Entries
. Остальные Users
не должны иметь никаких прав на работу с Journals
и Entries
.User
, который оставил Entry
(при условии, что он всё ещё имеет права на работу с журналом, т.е. присутствует в таблице journal_user
) может редактировать её. Остальные доверенные пользователи (из таблицы journal_user
для текущего Journal
) могут только читать.Я не знаю, как подступиться к описанным выше требованиям к ограничениям. Самое удобное - сделать ограничение подобное на стороне middleware, который бы использовался в качестве middleware для группы роутов в web.php. И если с пользователем понятно (я могу получить его данные через Auth::user()), то как быть с Journal?
Route::get('journals/{journal}', 'JournalController@show')->name('journals.show');
Нужно проверить, что пользователь может открыть этот журнал. Значит на стороне middleware нужно как-то получить переданный параметр роута {journal}. Как это можно сделать?
Насчёт возможности редактирования только своей записи я вроде бы понимаю - реализовать можно через Request и валидацию (есть там метод auth). Но как быть с выше описанным? Это можно сделать как-то иначе? Да, я могу в каждом методе контроллеров проверять, но это же не правильно, да?
Как создать посредника маршрута в Laravel описано здесь middleware. Все действия сводятся к двум простым шагам - создание файла посредника и его последующая регистрация. Назначим на маршрут наш посредник:
Route::get('journals/{journal}', 'JournalController@show')
->name('journals.show')
->middleware('journal.control');
Код посредника:
use App\Models\JournalUsers;
class JournalControl
{
public function handle($request, Closure $next)
{
$journal = $request->route('journal');
if($this->checkJournalRight($journal) {
return $next($request);
}
return abort(404);
}
public function checkJournalRight($journal_id)
{
if(
JournalUsers::where('user_id', session()->get('user_id'))
->where('journal_id', $journal_id)
->first()
) {
return true;
}
return false;
}
Все легко и просто, в первом действии извлекаем параметр journal
с маршрута, и ищем в таблице права пользователя на указанный журнал.
Теперь о записях в журнале(предполагаю что это отдельная сущность в виде таблицы, где есть ключ на journal_id
и создателя user_id
).
use App\Models\Entries;
public function checkRight()
{
$right = Entries::where('user_id', session()->get('user_id'))
->where('journal_id', $request->route('journal'))
->where('id', $request->route('entry'))
->first();
return (!empty($right)) ? true : false;
}
Использовать код в посреднике или контролере решать Вам. Код маршрута может выглядеть примерно так:
Route::get('journals/{journal}/entries/{entry}');
PS. Код написан на чистом энтузиазме. Я никогда не использовал стандартную регистрацию Laravel. Используйте свои данные вместо моих.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Всем доброго времени сутокВозник вопрос, как мне от текущего времени отнять время из бд? У меня есть табличка с типом Time, там пока около 20 записей,...
Пишу свой велосипед, который будет из себя представлять менеджер паролей для входа на сайты (да, знаю, что в браузерах есть куча готовых решений,...