Добавление роли пользователя. Установка роли по умолчанию при регистрации и команда смены роли администратором. Команда удаления неактивного пользователя.
В следующем эпизоде мы подключим БД и добавим сохранение наших сущностей. И далее уже напишем контроллеры.
Чтобы не пропускать новые эпизоды подпишитесь на наш канал @deworkerpro в Telegram
Спасибо. Очень хорошо.
Спасибо, Дмитрий! Интересен такой момент: вы неоднократно упоминали о подходе Test First. При разработке задачи, к примеру, создания эндпойнта изменения пароля пользователя, на ваш взгляд, следует вначале разработать сценарии взаимодействия с этим эндпойнтом в тестах, а уж затем разработать модульные тесты для проверки метода changePassword у агрегата пользователя, или наоборот, разработать модульные тесты для changePassword, реализовать код для прохождения этих тестов, а уж затем разрабатывать тесты для взаимодействия с эндпойнтом изменения пароля? Или, может быть, какой-то третий вариант?
Всегда лучше делать так, как будет удобнее.
Если уже есть полные требования к эндпойнту со стороны заказчика, то их можно сразу описать в приёмочных или функциональных тестах и пока эти невыполняющиеся тесты пометить игнорируемыми. А потом реализовать всё в коде, чтобы они прошли.
Если же мы не знаем, какой точно будет эндпоинт, то можно сначала придумать команду и на ходу пробовать придумывать классы и методы одновременно с тестами, как делали мы.
Спасибо за урок. У меня вопрос не имеющий отношения к программированию =) Согласно GDPR, пользователь должен иметь возможность удалять данные о себе целиком с сервиса. И как тогда решать проблему удаления? Нам не нужны висячие транзакции, но и удалить их нельзя. Как это решается у больших мальчиков? =)
Корпоративная тайна)
Я, конечно, такой вариант тоже рассматриваю, но потом терморектальные процедуры могут быть прописаны от надзорных органов. Поэтому как-то стрёмно
Очень просто, все данные заменяются, например фио на удаленный пользователь номер такойто, телефоны и емейлы на фейки и все.
Всё верно - данные обезличиваются, можно сделать через хеш
Если используются хранилища вроде Kafka без возможности редактировать старые записи, то для слишком чувствительных данных обычно вместо них записывают значения, зашифрованные ключом, который хранится отдельно у каждого пользователя. Потом просто удаляют этот ключ.
Дмитрий. Здравствуйте.
Очень было бы интересно рассмотреть правильную архитектуру и работу с: городами, областями, странами, геокоординатами, улицами и т. д.
Здесь волнует такой вопрос, что гео используется во многих сервисах сайта. Получается это гео надо выносить в свой сервис. Так же не понятно как лучше хранить данные: id, координаты, строка. Какие данные можно получать по связям, а какие надо хранить в сущности.
Очень благодарен был бы за рассмотрение этого подхода и работу со сторонними сервисами типа Яндекс, Гугл и др.
А так же загрузку использование своего общего аватара (на подобии gavatar). Но это в принципе понятно. Но тоже интересно.
Города и страны можно вынести оидельно, а всем сущностям присваивать только их идентификаторы.
Если нужны просто координаты, то можно записывать в
new Coordinate(lat, long)
В доменной сущности нужно хранить только необходимый минимум. Ей хватит только идентификатора.
Связи обычно нужны только для отображения на фронтенде. Поэтому для отображения удобно делать отдельные голые SQL-запросы со всеми нужными нам JOIN-ами. До этого дойдём когда помимо Command начнём делать Query.
Благодарю!
Дмитрий, а можно вопрос: вы изменяете историю коммитов или ребейз делаете? У меня гиткракен иногда смещает историю при ваших обновлениях на ориджине. Мне приходится резет делать на мастер/ориджин из-за конфликта с текущей одной единственной веткой :)
Да, старые коммиты понемногу исправляются интерактивным ребейзом.
Спасибо за ответ. Я думал у меня гиткракен глючит :)
У меня такой вопрос. Допустим, в будущем нам понадобится возможность для каждого товара аукциона настроить видимость по ролям. То есть только пользователи с определенными ролями могут просматривать товар, а с какими именно ролями — настраивается в каждом конкретном товаре. Получается, что где-то в модуле Auction будет свой класс Role или Roles, в котором тоже будут использоваться константы USER и ADMIN.
Как в этом случае поступить? Можно ли вынести эти константы в общий интерфейс, например RoleInterface, и сделать так, чтобы классы в обоих модулях реализовывали этот интерфейс? Или константы в каждом классе должны быть свои? Тогда где их потом сопоставлять?
Если вариант с общим интерфейсом подходит, то где его разместить? Если оставить его в модуле Auth, то получится, что класс одного модуля реализует интерфейс из другого, и модули как бы перестают быть независимыми. Или сделать отдельную папку Interface за пределами модулей и все общие интерфейсы выносить туда?
Возможность просмотра производится чаще не ролями, а разрешениями. В каждом модуле храним и проверяем именно его разрешения. И уже эти разрешения привязываем к ролям снаружи.
С ролями действительно получился неудачный пример. Мой вопрос был более общий: насколько корректно, когда классы в разных модулях реализуют какой-то единый интерфейс. Получается, что все-таки так делать не надо? И даже если в разных модулях задействованы одни и те же константы, то они всё равно должны быть у каждого модуля свои. А снаружи уже всё это сопоставляем. Верно?
Если это просто общий код, то спокойно его используем вроде нашего
Flusher
из корня. Если же нужна именно логика из другого модуля, то как компромисс можем у одного объявить интерфейс, а снаружи к нему реализовать адаптер. Но корректнее это будет реализовать в виде обмена сообщениями через очередь.Понял, спасибо
Добрый день! Отличный урок, но непонятно, как все-таки правильно разбивать логику с уже удаленным пользователем. Например у нас есть метод подтверждения пользователя по смс или звонку, а пользователя мы удалили. Где мы делаем проверку?
И вопрос такого же характера. Есть у нас например роли User и Manager. Manager может создавать и удалять пользователя, но пока мы не делаем RemoveByManager, а просто Remove. В этом случае, я так понимаю все надо оставлять в Контроллерах приложения, а задача нашего модуля только в том, чтобы предоставить базовый функционал, а приложение уже само решает как им распоряжаться?
Если мы его действительно удалили, то и токен подтверждения удалится из БД. И пользователь и так не найдётся по токену.
Если же мы не удалили пользователя, а просто заблокировали или архивировали, то тогда ближе всего будет сделать проверку прямо в его методе
confirm
.Да, обычно при простом RBAC роли проверяют в контроллерах. Отдельные команды вроде RemoveByManager нужны если там что-то будет отличаться.
Дмитрий, можно вопрос, будете учитывать случай когда у пользователя одновременно две роли (продавец и покупатель), сможете рассмотреть в одном из следующих эпизодов внедрение RBAC, ABAC или другой модели ролей/разрешений которая лучше для этого подходит? Спасибо.
Продавец, покупатель и другие подобные бизнес-роли как раз можно делать на доменном уровне вроде ABAC. Например, проверками в модуле магазина, что есть сущность "Продавец" или сущность "Покупатель" с таким ID пользователя. А в RBAC указывать только глобальные роли вроде
user
иadmin
для всей системы.А если это делать в RBAC именно ролями продавца и покупателя, то тогда можно сделать привязку пользователю и помещение в токен не одной роли, а массива.
Добрый день. В приложении имеется компании, магазины и товары. Пользователь должен работать только с теми товарами которые имеются в магазине его компании (руководитель конкретной компании), или только конкретного магазина (руководитель конкретного магазина). Какой паттерн/методику посоветуете?
Если владельцев может быть несколько, то добавить many-to-many связи вроде
company_owners(company_id, user_id)
иshop_owners(shop_id, user_id)
. И уже по ним вычислять доступы.Добрый день, подскажите, не совсем понял вот этот фрагмент кода с удалением:
Будет ли в следующих уроках какая-то проверка в методе
$this->users->remove()
, чтобы было нельзя удалить пользователя без проверки на удаление в$user->remove()
?Пока складывается впечатление, что можно удалить активного пользователя просто проигнорировав проверку.
Метод
$user->remove()
проверяет бизнес-правила удаления и в будущем может генерировать событие удаления.Проверять на бизнес-правила удаления в самом репозитории
$this->users->remove($user)
не очень уместно, так как репозиторий нам нужен именно для физического удаления записи из БД.Так что риск есть, но лучше оставить всё как есть.
Или войти через: