77 */
88
99import { Injector } from '@angular/core' ;
10- import { MonoTypeOperatorFunction , Observable , from , of } from 'rxjs' ;
11- import { concatMap , every , first , map , mergeMap } from 'rxjs/operators' ;
10+ import { MonoTypeOperatorFunction , Observable , defer , from , of } from 'rxjs' ;
11+ import { concatAll , concatMap , first , map , mergeMap } from 'rxjs/operators' ;
1212
1313import { ActivationStart , ChildActivationStart , Event } from '../events' ;
1414import { CanActivateChildFn , CanActivateFn , CanDeactivateFn } from '../interfaces' ;
1515import { NavigationTransition } from '../router' ;
1616import { ActivatedRouteSnapshot , RouterStateSnapshot } from '../router_state' ;
1717import { UrlTree } from '../url_tree' ;
18- import { andObservables , wrapIntoObservable } from '../utils/collection' ;
18+ import { wrapIntoObservable } from '../utils/collection' ;
1919import { CanActivate , CanDeactivate , getCanActivateChild , getToken } from '../utils/preactivation' ;
20- import { isCanActivate , isCanActivateChild , isCanDeactivate , isFunction } from '../utils/type_guards' ;
20+ import { isCanActivate , isCanActivateChild , isCanDeactivate , isFunction , isBoolean } from '../utils/type_guards' ;
21+
22+ import { prioritizedGuardValue } from './prioritized_guard_value' ;
2123
2224export function checkGuards ( moduleInjector : Injector , forwardEvent ?: ( evt : Event ) => void ) :
2325 MonoTypeOperatorFunction < NavigationTransition > {
@@ -33,10 +35,10 @@ export function checkGuards(moduleInjector: Injector, forwardEvent?: (evt: Event
3335 canDeactivateChecks , targetSnapshot ! , currentSnapshot , moduleInjector )
3436 . pipe (
3537 mergeMap ( canDeactivate => {
36- return canDeactivate ?
38+ return canDeactivate && isBoolean ( canDeactivate ) ?
3739 runCanActivateChecks (
3840 targetSnapshot ! , canActivateChecks , moduleInjector , forwardEvent ) :
39- of ( false ) ;
41+ of ( canDeactivate ) ;
4042 } ) ,
4143 map ( guardsResult => ( { ...t , guardsResult} ) ) ) ;
4244 } ) ) ;
@@ -45,25 +47,30 @@ export function checkGuards(moduleInjector: Injector, forwardEvent?: (evt: Event
4547
4648function runCanDeactivateChecks (
4749 checks : CanDeactivate [ ] , futureRSS : RouterStateSnapshot , currRSS : RouterStateSnapshot ,
48- moduleInjector : Injector ) : Observable < boolean | UrlTree > {
50+ moduleInjector : Injector ) {
4951 return from ( checks ) . pipe (
50- mergeMap ( check => {
51- return runCanDeactivate ( check . component , check . route , currRSS , futureRSS , moduleInjector ) ;
52- } ) ,
53- every ( result => result === true ) ) ;
52+ mergeMap (
53+ check =>
54+ runCanDeactivate ( check . component , check . route , currRSS , futureRSS , moduleInjector ) ) ,
55+ first ( result => { return result !== true ; } , true as boolean | UrlTree ) ) ;
5456}
5557
5658function runCanActivateChecks (
5759 futureSnapshot : RouterStateSnapshot , checks : CanActivate [ ] , moduleInjector : Injector ,
58- forwardEvent ?: ( evt : Event ) => void ) : Observable < boolean > {
60+ forwardEvent ?: ( evt : Event ) => void ) {
5961 return from ( checks ) . pipe (
60- concatMap ( ( check : CanActivate ) => andObservables ( from ( [
61- fireChildActivationStart ( check . route . parent , forwardEvent ) ,
62- fireActivationStart ( check . route , forwardEvent ) ,
63- runCanActivateChild ( futureSnapshot , check . path , moduleInjector ) ,
64- runCanActivate ( futureSnapshot , check . route , moduleInjector )
65- ] ) ) ) ,
66- every ( ( result : boolean ) => result === true ) ) ;
62+ concatMap ( ( check : CanActivate ) => {
63+ return from ( [
64+ fireChildActivationStart ( check . route . parent , forwardEvent ) ,
65+ fireActivationStart ( check . route , forwardEvent ) ,
66+ runCanActivateChild ( futureSnapshot , check . path , moduleInjector ) ,
67+ runCanActivate ( futureSnapshot , check . route , moduleInjector )
68+ ] )
69+ . pipe ( concatAll ( ) , first ( result => {
70+ return result !== true ;
71+ } , true as boolean | UrlTree ) ) ;
72+ } ) ,
73+ first ( result => { return result !== true ; } , true as boolean | UrlTree ) ) ;
6774}
6875
6976/**
@@ -102,57 +109,63 @@ function fireChildActivationStart(
102109
103110function runCanActivate (
104111 futureRSS : RouterStateSnapshot , futureARS : ActivatedRouteSnapshot ,
105- moduleInjector : Injector ) : Observable < boolean > {
112+ moduleInjector : Injector ) : Observable < boolean | UrlTree > {
106113 const canActivate = futureARS . routeConfig ? futureARS . routeConfig . canActivate : null ;
107114 if ( ! canActivate || canActivate . length === 0 ) return of ( true ) ;
108- const obs = from ( canActivate ) . pipe ( map ( ( c : any ) => {
109- const guard = getToken ( c , futureARS , moduleInjector ) ;
110- let observable ;
111- if ( isCanActivate ( guard ) ) {
112- observable = wrapIntoObservable ( guard . canActivate ( futureARS , futureRSS ) ) ;
113- } else if ( isFunction < CanActivateFn > ( guard ) ) {
114- observable = wrapIntoObservable ( guard ( futureARS , futureRSS ) ) ;
115- } else {
116- throw new Error ( 'Invalid canActivate guard' ) ;
117- }
118- return observable . pipe ( first ( ) ) ;
119- } ) ) ;
120- return andObservables ( obs ) ;
115+
116+ const canActivateObservables = canActivate . map ( ( c : any ) => {
117+ return defer ( ( ) => {
118+ const guard = getToken ( c , futureARS , moduleInjector ) ;
119+ let observable ;
120+ if ( isCanActivate ( guard ) ) {
121+ observable = wrapIntoObservable ( guard . canActivate ( futureARS , futureRSS ) ) ;
122+ } else if ( isFunction < CanActivateFn > ( guard ) ) {
123+ observable = wrapIntoObservable ( guard ( futureARS , futureRSS ) ) ;
124+ } else {
125+ throw new Error ( 'Invalid CanActivate guard' ) ;
126+ }
127+ return observable . pipe ( first ( ) ) ;
128+ } ) ;
129+ } ) ;
130+ return of ( canActivateObservables ) . pipe ( prioritizedGuardValue ( ) ) ;
121131}
122132
123133function runCanActivateChild (
124134 futureRSS : RouterStateSnapshot , path : ActivatedRouteSnapshot [ ] ,
125- moduleInjector : Injector ) : Observable < boolean > {
135+ moduleInjector : Injector ) : Observable < boolean | UrlTree > {
126136 const futureARS = path [ path . length - 1 ] ;
127137
128138 const canActivateChildGuards = path . slice ( 0 , path . length - 1 )
129139 . reverse ( )
130140 . map ( p => getCanActivateChild ( p ) )
131141 . filter ( _ => _ !== null ) ;
132142
133- return andObservables ( from ( canActivateChildGuards ) . pipe ( map ( ( d : any ) => {
134- const obs = from ( d . guards ) . pipe ( map ( ( c : any ) => {
135- const guard = getToken ( c , d . node , moduleInjector ) ;
136- let observable ;
137- if ( isCanActivateChild ( guard ) ) {
138- observable = wrapIntoObservable ( guard . canActivateChild ( futureARS , futureRSS ) ) ;
139- } else if ( isFunction < CanActivateChildFn > ( guard ) ) {
140- observable = wrapIntoObservable ( guard ( futureARS , futureRSS ) ) ;
141- } else {
142- throw new Error ( 'Invalid CanActivateChild guard' ) ;
143- }
144- return observable . pipe ( first ( ) ) ;
145- } ) ) ;
146- return andObservables ( obs ) ;
147- } ) ) ) ;
143+ const canActivateChildGuardsMapped = canActivateChildGuards . map ( ( d : any ) => {
144+ return defer ( ( ) => {
145+ const guardsMapped = d . guards . map ( ( c : any ) => {
146+ const guard = getToken ( c , d . node , moduleInjector ) ;
147+ let observable ;
148+ if ( isCanActivateChild ( guard ) ) {
149+ observable = wrapIntoObservable ( guard . canActivateChild ( futureARS , futureRSS ) ) ;
150+ } else if ( isFunction < CanActivateChildFn > ( guard ) ) {
151+ observable = wrapIntoObservable ( guard ( futureARS , futureRSS ) ) ;
152+ } else {
153+ throw new Error ( 'Invalid CanActivateChild guard' ) ;
154+ }
155+ return observable . pipe ( first ( ) ) ;
156+ } ) ;
157+ return of ( guardsMapped ) . pipe ( prioritizedGuardValue ( ) ) ;
158+ } ) ;
159+ } ) ;
160+ return of ( canActivateChildGuardsMapped ) . pipe ( prioritizedGuardValue ( ) ) ;
148161}
149162
150163function runCanDeactivate (
151- component : Object | null , currARS : ActivatedRouteSnapshot , currRSS : RouterStateSnapshot ,
164+ component : Object | null , currARS : ActivatedRouteSnapshot , currRSS : RouterStateSnapshot ,
152165 futureRSS : RouterStateSnapshot , moduleInjector : Injector ) : Observable < boolean | UrlTree > {
153166 const canDeactivate = currARS && currARS . routeConfig ? currARS . routeConfig . canDeactivate : null ;
154167 if ( ! canDeactivate || canDeactivate . length === 0 ) return of ( true ) ;
155- const canDeactivate$ = from ( canDeactivate ) . pipe ( mergeMap ( ( c : any ) => {
168+ const canDeactivateObservables = canDeactivate . map ( ( c : any ) => {
156169 const guard = getToken ( c , currARS , moduleInjector ) ;
157170 let observable ;
158171 if ( isCanDeactivate ( guard ) ) {
@@ -164,6 +177,6 @@ function runCanDeactivate(
164177 throw new Error ( 'Invalid CanDeactivate guard' ) ;
165178 }
166179 return observable . pipe ( first ( ) ) ;
167- } ) ) ;
168- return canDeactivate$ . pipe ( every ( ( result : any ) => result === true ) ) ;
180+ } ) ;
181+ return of ( canDeactivateObservables ) . pipe ( prioritizedGuardValue ( ) ) ;
169182}
0 commit comments