Я работаю над приложением, у которого есть много ролей, которые мне нужно использовать для блокировки навигации к частям приложения на основе этих ролей. Я понимаю, что могу создавать отдельные классы защиты для каждой роли, но предпочитаю иметь один класс, в который я мог бы каким-то образом передать параметр. Другими словами, я хотел бы сделать что-то подобное:
{
path: 'super-user-stuff',
component: SuperUserStuffComponent,
canActivate: [RoleGuard.forRole('superUser')]
}
Но поскольку все, что вы передаете, - это имя типа вашего охранника, не могу придумать, как это сделать. Должен ли я просто укусить пулю и написать отдельные классы защиты для каждой роли и разрушить мою иллюзию элегантности, имея вместо этого один параметризованный тип?
angular
typescript
angular2-routing
Брайан Нойес
источник
источник
roles
объект и средство защиты маршрута связаны, не зная заранее, как работает код. Отстойно, что Angular не поддерживает способ сделать это более декларативным способом. (Чтобы прояснить, я оплакиваю Angular, а не это совершенно разумное решение.)Вот мой взгляд на это и возможное решение проблемы с отсутствующим поставщиком.
В моем случае у нас есть охранник, который принимает разрешение или список разрешений в качестве параметра, но это то же самое, что имеет роль.
У нас есть класс для работы с охранниками авторизации с разрешения или без разрешения:
Это касается проверки активного сеанса пользователя и т. Д.
Он также содержит метод, используемый для получения настраиваемой защиты разрешений, которая фактически зависит от
AuthGuardService
самогоЭто позволяет нам использовать метод для регистрации некоторых настраиваемых охранников на основе параметра разрешений в нашем модуле маршрутизации:
Интересная часть
forPermission
заключаетсяAuthGuardService.guards.push
в том, что это в основном гарантирует, что каждый раз, когдаforPermissions
вызывается для получения настраиваемого класса защиты, он также сохраняет его в этом массиве. Это также статично для основного класса:Затем мы можем использовать этот массив для регистрации всех охранников - это нормально, если мы убедимся, что к тому времени, когда модуль приложения зарегистрирует этих поставщиков, маршруты были определены и все классы защиты были созданы (например, проверьте порядок импорта и держите этих провайдеров как можно ниже в списке - помогает наличие модуля маршрутизации):
Надеюсь это поможет.
источник
ERROR in Error during template compile of 'RoutingModule' Function calls are not supported in decorators but 'PermGuardService' was called.
Решение @AluanHaddad выдает ошибку «нет провайдера». Вот исправление для этого (это кажется грязным, но у меня нет навыков, чтобы исправить это).
По сути, я регистрирую как поставщик каждый динамически генерируемый класс, созданный с помощью
roleGuard
.Итак, для каждой проверенной роли:
у вас должно быть:
Однако решение @AluanHaddad как есть будет генерировать новый класс для каждого вызова
roleGuard
, даже еслиroles
параметр тот же. Использованиеlodash.memoize
это выглядит так:Обратите внимание, что каждая комбинация ролей генерирует новый класс, поэтому вам необходимо зарегистрировать в качестве поставщика каждую комбинацию ролей. Т.е. если у вас есть:
canActivate: [roleGuard('foo')]
иcanActivate: [roleGuard('foo', 'bar')]
вам нужно будет зарегистрировать оба:providers[roleGuard('foo'), roleGuard('foo', 'bar')]
Лучшим решением было бы автоматически регистрировать поставщиков в глобальной коллекции поставщиков внутри
roleGuard
, но, как я уже сказал, мне не хватает навыков для этого.источник