Pracuję nad aplikacją, która ma wiele ról, które muszę używać strażników, aby blokować nawigację do części aplikacji w oparciu o te role. Zdaję sobie sprawę, że mogę utworzyć indywidualne klasy ochrony dla każdej roli, ale wolałbym mieć jedną klasę, do której mógłbym w jakiś sposób przekazać parametr. Innymi słowy, chciałbym móc zrobić coś podobnego do tego:
{
path: 'super-user-stuff',
component: SuperUserStuffComponent,
canActivate: [RoleGuard.forRole('superUser')]
}
Ale ponieważ wszystko, co mijasz, to nazwa typu twojego strażnika, nie możesz wymyślić sposobu, aby to zrobić. Czy powinienem po prostu ugryźć punktor i napisać poszczególne klasy strażników według roli i zburzyć iluzję elegancji, mając zamiast tego jeden sparametryzowany typ?
angular
typescript
angular2-routing
Brian Noyes
źródło
źródło
roles
obiekt i strażnik trasy są połączone, nie wiedząc wcześniej, jak działa kod. Szkoda, że Angular nie obsługuje sposobu, aby to zrobić w bardziej deklaratywny sposób. (Żeby było jasne, to jaOto moje podejście do tego i możliwe rozwiązanie problemu z brakującym dostawcą.
W moim przypadku mamy strażnika, który jako parametr przyjmuje pozwolenie lub listę uprawnień, ale to samo ma rolę.
Mamy klasę do radzenia sobie ze strażnikami auth z pozwoleniem lub bez:
Dotyczy to sprawdzania aktywnej sesji użytkownika itp.
Zawiera również metodę używaną do uzyskiwania niestandardowej ochrony uprawnień, która w rzeczywistości zależy od
AuthGuardService
siebieTo pozwala nam użyć metody do zarejestrowania niektórych niestandardowych strażników na podstawie parametru permissions w naszym module routingu:
Interesującą częścią
forPermission
jestAuthGuardService.guards.push
to, że w zasadzie zapewnia to, że za każdym razem, gdyforPermissions
zostanie wywołana w celu uzyskania niestandardowej klasy ochrony, będzie ona również przechowywać ją w tej tablicy. Jest to również statyczne w głównej klasie:Następnie możemy użyć tej tablicy do zarejestrowania wszystkich strażników - jest to w porządku, o ile upewnimy się, że zanim moduł aplikacji zarejestruje tych dostawców, trasy zostały zdefiniowane i wszystkie klasy ochrony zostały utworzone (np. Sprawdź kolejność importu i utrzymuj tych dostawców jak najniżej na liście - posiadanie modułu routingu pomaga):
Mam nadzieję że to pomoże.
źródło
ERROR in Error during template compile of 'RoutingModule' Function calls are not supported in decorators but 'PermGuardService' was called.
Rozwiązanie @ AluanHaddad wyświetla błąd „brak dostawcy”. Oto rozwiązanie tego problemu (wydaje się brudne, ale brakuje mi umiejętności, aby ulepszyć).
Koncepcyjnie rejestruję jako dostawca każdą dynamicznie generowaną klasę utworzoną przez
roleGuard
.Więc dla każdej sprawdzonej roli:
powinieneś mieć:
Jednak rozwiązanie @ AluanHaddad w stanie obecnym wygeneruje nową klasę dla każdego wywołania
roleGuard
, nawet jeśliroles
parametr jest taki sam. Używanielodash.memoize
go wygląda następująco:Zauważ, że każda kombinacja ról generuje nową klasę, więc musisz zarejestrować jako dostawca każdą kombinację ról. To znaczy, jeśli masz:
canActivate: [roleGuard('foo')]
icanActivate: [roleGuard('foo', 'bar')]
będziesz musiał zarejestrować oba:providers[roleGuard('foo'), roleGuard('foo', 'bar')]
Lepszym rozwiązaniem byłoby automatyczne rejestrowanie dostawców w globalnej kolekcji dostawców wewnątrz
roleGuard
, ale jak powiedziałem, brakuje mi umiejętności, aby to zaimplementować.źródło