Ich arbeite an einer App mit vielen Rollen, die ich mithilfe von Wachen verwenden muss, um die Navigation für Teile der App basierend auf diesen Rollen zu blockieren. Mir ist klar, dass ich für jede Rolle individuelle Schutzklassen erstellen kann, aber lieber eine Klasse hätte, an die ich irgendwie einen Parameter übergeben könnte. Mit anderen Worten, ich möchte in der Lage sein, etwas Ähnliches zu tun:
{
path: 'super-user-stuff',
component: SuperUserStuffComponent,
canActivate: [RoleGuard.forRole('superUser')]
}
Aber da alles, was Sie passieren, der Typname Ihrer Wache ist, können Sie sich keinen Weg vorstellen, dies zu tun. Sollte ich einfach in die Kugel beißen und die einzelnen Schutzklassen pro Rolle schreiben und meine Illusion von Eleganz zerstören, stattdessen einen einzigen parametrisierten Typ zu haben?
quelle
roles
Objekt und der Routenwächter miteinander verbunden sind, ohne vorher zu wissen, wie der Code funktioniert. Es ist schade, dass Angular keine Möglichkeit unterstützt, dies deklarativer zu tun. (Um klar zu sein, beklage ich Angular nicht diese völlig vernünftige Lösung.)Hier ist meine Meinung dazu und eine mögliche Lösung für das fehlende Anbieterproblem.
In meinem Fall haben wir einen Guard, der eine Berechtigung oder eine Liste von Berechtigungen als Parameter verwendet, aber es ist dasselbe, das eine Rolle spielt.
Wir haben eine Klasse für den Umgang mit Auth Guards mit oder ohne Erlaubnis:
Dies befasst sich mit der Überprüfung der aktiven Sitzung des Benutzers usw.
Es enthält auch eine Methode zum Abrufen eines benutzerdefinierten Berechtigungsschutzes, die tatsächlich von sich
AuthGuardService
selbst abhängtAuf diese Weise können wir die Methode verwenden, um einige benutzerdefinierte Schutzvorrichtungen basierend auf Berechtigungsparametern in unserem Routingmodul zu registrieren:
Der interessante Teil von
forPermission
istAuthGuardService.guards.push
- dies stellt im Grunde sicher, dass jedes Mal, wennforPermissions
eine benutzerdefinierte Schutzklasse aufgerufen wird, diese auch in diesem Array gespeichert wird. Dies gilt auch für die Hauptklasse:Dann können wir dieses Array verwenden, um alle Wachen zu registrieren - dies ist in Ordnung, solange wir sicherstellen, dass zum Zeitpunkt der Registrierung dieser Anbieter durch das App-Modul die Routen definiert und alle Wächterklassen erstellt wurden (z. B. Importreihenfolge überprüfen und Halten Sie diese Anbieter in der Liste so niedrig wie möglich - ein Routing-Modul hilft):
Hoffe das hilft.
quelle
ERROR in Error during template compile of 'RoutingModule' Function calls are not supported in decorators but 'PermGuardService' was called.
Die Lösung von @ AluanHaddad gibt den Fehler "kein Anbieter" aus. Hier ist eine Lösung dafür (es fühlt sich schmutzig an, aber mir fehlen die Fähigkeiten, um eine bessere zu machen).
Konzeptionell registriere ich als Anbieter jede dynamisch generierte Klasse, die von erstellt wurde
roleGuard
.Also für jede überprüfte Rolle:
du solltest haben:
Die aktuelle Lösung von @ AluanHaddad generiert jedoch für jeden Aufruf von eine neue Klasse
roleGuard
, auch wenn derroles
Parameter derselbe ist. Die Verwendunglodash.memoize
sieht folgendermaßen aus:Beachten Sie, dass jede Rollenkombination eine neue Klasse generiert. Sie müssen daher jede Rollenkombination als Anbieter registrieren . Dh wenn Sie haben:
canActivate: [roleGuard('foo')]
undcanActivate: [roleGuard('foo', 'bar')]
Sie müssen beide registrieren:providers[roleGuard('foo'), roleGuard('foo', 'bar')]
Eine bessere Lösung wäre, Anbieter automatisch in einer globalen Anbietersammlung zu registrieren
roleGuard
, aber wie gesagt, mir fehlen die Fähigkeiten, dies umzusetzen.quelle