[Feature Request] authCanMatchGuard + helpers
- Lingua principale
- TypeScript
- Stelle
- 7.8k
- Fork
- 2.2k
- Merge medio
- 22h 28m
- PR unite (30g)
- 6
Descrizione
# Feature Request - authCanMatchGuard + helpers
## Description
The current auth-guard provided with angular fire is still using the [now deprecated](https://github.com/angular/angular/pull/47924) class based approach and targets the `canActivate` property on route definitions.
To freshen things up a bit, I have generated a new guard which utilizes the new functional approach and targets the newer `canMatch` route definition property. This has the added benefit of preventing components from being unnecessarily loaded which seems to work well and should be more performant.
I based the new code off of the previous implementation [documented here](https://github.com/angular/angularfire/blob/3639e41b52c0b2963c1e24734ff8401f4d21107e/site/src/auth/route-guards.md). You will notice similarities with [the previous guard code here](https://github.com/angular/angularfire/blob/3639e41b52c0b2963c1e24734ff8401f4d21107e/src/auth-guard/auth-guard.ts). Would love to see this incorporated into the AngularFire package but honestly I'm too lazy to write tests 😅 so if someone would be interested in owning that and collaborating, I'd be happy to open up a PR.
## Code
`auth-can-match.guard.ts`
```
import { inject } from '@angular/core';
import { Auth, user, User } from '@angular/fire/auth';
import { CanMatchFn, Route, Router, UrlSegment } from '@angular/router';
import { Observable, of, pipe, UnaryFunction } from 'rxjs';
import { map, switchMap, take } from 'rxjs/operators';
/** Utility type to allow for adding an additional property to the CanMatchFn type */
type ExtendFn = BaseFnT extends (...a: infer P) => infer R
? (...a: [...P, ...AddPT]) => R
: never
export type AuthPipe = UnaryFunction, Observable>;
export const authCanMatchGuard: ExtendFn = (route, segments, authPipe?) => {
const auth = inject(Auth)
const user$ = user(auth)
const router = inject(Router)
const authPipeFactory = authPipe
? authPipe
: loggedIn
return user$
.pipe(
take(1),
authPipeFactory,
map(can => {
if (typeof can === 'boolean') {
return can;
} else if (Array.isArray(can)) {
return router.createUrlTree(can)
} else {
return router.parseUrl(can)
}
})
)
}
/** canMatch helper to be used with spread operator to make route definitions more concise.
* @example
* const redirectUnauthorizedToLogin = redirectUnauthorizedTo(['login'])
* ...
* export const routes: Routes = [
* {
* ...authCanMatch(redirectUnauthorizedToLogin)
* path: 'authProtectedRoute'
* },
*/
export const authCanMatch = (authPipe: AuthPipe) =>
({ canMatch: [(route: Route, segments: UrlSegment[]) => authCanMatchGuard(route, segments, authPipe)] })
/** Predefined auth guard helper pipes. So friendly & helpful 😍 */
export const loggedIn: AuthPipe = map(user => !!user)
export const isNotAnonymous: AuthPipe = map(user => !!user && !user.isAnonymous)
export const idTokenResult = switchMap((user: User | null) => user ? user.getIdTokenResult() : of(null))
export const emailVerified: AuthPipe = map(user => !!user && user.emailVerified)
export const customClaims = pipe(idTokenResult, map(idTokenResult => idTokenResult ? idTokenResult.claims : []))
export const hasCustomClaim: (claim: string) => AuthPipe =
// eslint-disable-next-line no-prototype-builtins
(claim) => pipe(customClaims, map(claims => claims.hasOwnProperty(claim)))
export const redirectUnauthorizedTo: (redirect: string | any[]) => AuthPipe =
(redirect) => pipe(loggedIn, map(loggedIn => loggedIn || redirect))
export const redirectLoggedInTo: (redirect: string | any[]) => AuthPipe =
(redirect) => pipe(loggedIn, map(loggedIn => loggedIn && redirect || true))
```
Guida per i contributori
Apri la guida per i contributori
Direzione di ricerca
Leggi prima src/auth-guard/auth-guard.ts e site/src/auth/route-guards.md, quindi confrontali con l'implementazione proposta di auth-can-match.guard.ts. Il lavoro è completato quando il guard canMatch funzionale e gli helper sono integrati in AngularFire e vengono aggiunti test per il loro comportamento di autenticazione e reindirizzamento.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- angular, firebase, typescript
- Ambito
- authentication, frontend
- Tipo di issue
- Funzionalità
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Ferma
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 35/100