@christianacca/angular-swa-auth
Advanced tools
Comparing version 1.1.2 to 2.0.0-beta.1
@@ -567,3 +567,8 @@ (function (global, factory) { | ||
*/ | ||
var hasSomeAllowedRoles = function (allowedRoles, actualRoles) { return allowedRoles.length === 0 || allowedRoles.includes(anonymousRole) || allowedRoles.some(function (r) { return actualRoles.includes(r); }); }; | ||
var hasSomeAllowedRoles = function (allowedRoles, actualRoles) { | ||
var allowedRoleNames = allowedRoles.flat(10); | ||
return (allowedRoleNames.length === 0 || | ||
allowedRoleNames.includes(anonymousRole) || | ||
allowedRoleNames.some(function (r) { return actualRoles.includes(r); })); | ||
}; | ||
/** | ||
@@ -588,3 +593,3 @@ * The main service for working with authenticated users | ||
this.sessionEvents$ = this.sessionEvents.asObservable(); | ||
this.userLoaded$ = rxjs.defer(function () { return _this.httpGet('/.auth/me'); }).pipe(operators.map(function (resp) { return resp.clientPrincipal; }), operators.tap(function (user) { | ||
this.currentUser$ = rxjs.defer(function () { return _this.httpGet('/.auth/me'); }).pipe(operators.map(function (resp) { return resp.clientPrincipal; }), operators.tap(function (user) { | ||
if (user) { | ||
@@ -594,4 +599,4 @@ _this.publishAuthenticatedSuccessEvents(user); | ||
}), operators.shareReplay({ bufferSize: 1, refCount: false })); | ||
this.isAuthenticated$ = this.userLoaded$.pipe(operators.map(function (user) { return !!user; }), operators.shareReplay({ bufferSize: 1, refCount: false })); | ||
this.currentIdp$ = this.userLoaded$.pipe(operators.map(function (user) { return user === null || user === void 0 ? void 0 : user.identityProvider; })); | ||
this.isAuthenticated$ = this.currentUser$.pipe(operators.map(function (user) { return !!user; }), operators.shareReplay({ bufferSize: 1, refCount: false })); | ||
this.currentIdp$ = this.currentUser$.pipe(operators.map(function (user) { return user === null || user === void 0 ? void 0 : user.identityProvider; })); | ||
} | ||
@@ -613,3 +618,3 @@ /** | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, this.userLoaded$.pipe(operators.first()).toPromise()]; | ||
case 0: return [4 /*yield*/, this.currentUser$.pipe(operators.first()).toPromise()]; | ||
case 1: | ||
@@ -629,7 +634,11 @@ user = _b.sent(); | ||
/** | ||
* Does the current user have one or more of the `allowedRoles` supplied | ||
* Does the current user have one or more of the `allowedRoles` supplied. | ||
* | ||
* Note: because the observable returned completes, consumers do NOT have to unsubscribe from it | ||
* | ||
* @param allowedRoles The list of roles to check | ||
* @return {Observable<boolean>} an observable that returns true/false and then completes | ||
*/ | ||
AuthService.prototype.hasSomeRoles$ = function (allowedRoles) { | ||
return this.userLoaded$.pipe(operators.map(function (user) { var _a; return hasSomeAllowedRoles(allowedRoles, (_a = user === null || user === void 0 ? void 0 : user.userRoles) !== null && _a !== void 0 ? _a : noExplicitRoles$1); })); | ||
return this.currentUser$.pipe(operators.map(function (user) { var _a; return hasSomeAllowedRoles(allowedRoles, (_a = user === null || user === void 0 ? void 0 : user.userRoles) !== null && _a !== void 0 ? _a : noExplicitRoles$1); }), operators.take(1)); | ||
}; | ||
@@ -682,3 +691,3 @@ /** | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, this.userLoaded$.toPromise()]; | ||
case 0: return [4 /*yield*/, this.currentUser$.toPromise()]; | ||
case 1: | ||
@@ -710,3 +719,3 @@ user = _b.sent(); | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, this.userLoaded$.toPromise()]; | ||
case 0: return [4 /*yield*/, this.currentUser$.toPromise()]; | ||
case 1: | ||
@@ -894,8 +903,8 @@ user = _b.sent(); | ||
* ```html | ||
* <nav class="menu" *swaRoleCheck="let isAdmin of ['admin']; let maybeAdmin = isPlaceholder"> | ||
* <nav class="menu" *swaRoleCheck="let canAdmin of ['admin']; let maybeCanAdmin = isPlaceholder"> | ||
* <p class="menu-label">Menu</p> | ||
* <ul class="menu-list"> | ||
* <a routerLink="/users" routerLinkActive="is-active"> | ||
* <progress *ngIf="maybeAdmin" class="progress is-primary is-medium" max="100">15%</progress> | ||
* <span *ngIf="!maybeAdmin" [ngClass]="!isAdmin ? 'has-text-grey-lighter' : ''">Users</span> | ||
* <progress *ngIf="maybeCanAdmin" class="progress is-primary is-medium" max="100">15%</progress> | ||
* <span *ngIf="!maybeCanAdmin" [ngClass]="!canAdmin ? 'has-text-grey-lighter' : ''">Users</span> | ||
* </a> | ||
@@ -946,3 +955,3 @@ * </ul> | ||
var _this = this; | ||
var injectedRoles$ = this.authService.userLoaded$.pipe(operators.map(function (user) { return user === null || user === void 0 ? void 0 : user.userRoles; }), operators.takeUntil(this.userRolesFromTemplate)); | ||
var injectedRoles$ = this.authService.currentUser$.pipe(operators.map(function (user) { return user === null || user === void 0 ? void 0 : user.userRoles; }), operators.takeUntil(this.userRolesFromTemplate)); | ||
var userRoles$ = rxjs.merge(this.userRolesFromTemplate, injectedRoles$).pipe(operators.map(function (x) { return x !== null && x !== void 0 ? x : noExplicitRoles; })); | ||
@@ -1029,10 +1038,14 @@ var permissionCheck$ = rxjs.combineLatest([this.allowedRoles, userRoles$]).pipe(operators.map(function (_a) { | ||
* | ||
* Implements `CanActivate` to ensure the user is authenticated before allowing the navigation to the route. | ||
* Where the user is not yet authenticated, trigger the login flow. | ||
* @see { AuthService.ensureLoggedIn} | ||
* Implements `CanLoad` for use with lazy loaded routes and `CanActivate` for regular routes. | ||
* | ||
* @see { AuthService.ensureLoggedIn } | ||
* @example | ||
* ```ts | ||
* export const routes: Routes = [ | ||
* { path: '', pathMatch: 'full', redirectTo: 'secure-page' }, | ||
* { path: 'secure-page', component: SecurePageComponent, canActivate: [AuthGuard] } | ||
* { path: 'secure-page', component: SecurePageComponent, canActivate: [AuthGuard] }, | ||
* { | ||
* path: 'product', | ||
* canLoad: [AuthGuard], | ||
* loadChildren: () => import('@christianacca/demo-app/product-admin').then(m => m.ProductAdminModule) | ||
* }, | ||
* ]; | ||
@@ -1042,4 +1055,5 @@ * ``` | ||
var AuthGuard = /** @class */ (function () { | ||
function AuthGuard(authService) { | ||
function AuthGuard(authService, router) { | ||
this.authService = authService; | ||
this.router = router; | ||
} | ||
@@ -1049,5 +1063,10 @@ AuthGuard.prototype.canActivate = function (_route, state) { | ||
}; | ||
AuthGuard.prototype.canLoad = function ( /* route: Route, segments: UrlSegment[] */) { | ||
var navigation = this.router.getCurrentNavigation(); | ||
var targetUrl = !navigation ? '/' : navigation.extractedUrl.toString(); | ||
return this.authService.ensureLoggedIn(targetUrl); | ||
}; | ||
return AuthGuard; | ||
}()); | ||
AuthGuard.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: AuthGuard, deps: [{ token: AuthService }], target: i0__namespace.ɵɵFactoryTarget.Injectable }); | ||
AuthGuard.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: AuthGuard, deps: [{ token: AuthService }, { token: i2__namespace.Router }], target: i0__namespace.ɵɵFactoryTarget.Injectable }); | ||
AuthGuard.ɵprov = i0__namespace.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: AuthGuard, providedIn: 'root' }); | ||
@@ -1059,3 +1078,3 @@ i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: AuthGuard, decorators: [{ | ||
}] | ||
}], ctorParameters: function () { return [{ type: AuthService }]; } }); | ||
}], ctorParameters: function () { return [{ type: AuthService }, { type: i2__namespace.Router }]; } }); | ||
@@ -1065,8 +1084,13 @@ /** | ||
* | ||
* Implements `CanActivate` to verify that the current user is a member of one or more roles | ||
* as defined in an `allowedRoles` field on `Route.data` for the route about to be navigated to | ||
* Implements `CanLoad` for use with lazy loaded routes and `CanActivate` for regular routes. | ||
* | ||
* Will first trigger the sign in flow when the user is not already authenticated. Then verifies | ||
* that the user is a member of one or more {@link AllowedRole}'s as defined in an `allowedRoles` | ||
* field on `Route.data` for the route about to be navigated to. | ||
* | ||
* Where the user is deemed unauthorized the SPA will be routed to the client-side route configured | ||
* using {@link AuthConfig.unauthorizedRoute} | ||
* | ||
* @see {AuthService.hasSomeRoles$} | ||
* | ||
* @example | ||
@@ -1076,8 +1100,16 @@ * ```ts | ||
* { | ||
* path: 'admin-page', | ||
* path: 'product-admin', | ||
* data: { | ||
* allowedRoles: 'admin' // or ['admin',] | ||
* allowedRoles: 'admin' // other ex: ['admin', 'owner'] ['admin', ['product-reader', 'owner']] | ||
* }, | ||
* canActivate: [SwaRoleGuard], | ||
* component: AdminComponent | ||
* }, | ||
* { | ||
* path: 'user-admin', | ||
* data: { | ||
* allowedRoles: 'owner' | ||
* }, | ||
* canLoad: [SwaRoleGuard], | ||
* loadChildren: () => import('@christianacca/demo-app/user-admin').then(m => m.UserAdminModule) | ||
* } | ||
@@ -1093,11 +1125,43 @@ * ]; | ||
} | ||
SwaRoleGuard.prototype.canActivate = function (route) { | ||
SwaRoleGuard.getAllowedRoles = function (route) { | ||
var _a; | ||
var roles = (_a = route.data) === null || _a === void 0 ? void 0 : _a.allowedRoles; | ||
if (!roles) { | ||
return undefined; | ||
} | ||
return Array.isArray(roles) ? roles : [roles]; | ||
}; | ||
SwaRoleGuard.prototype.canActivate = function (route, state) { | ||
return this.ensureHasRouteRoles(route, state.url); | ||
}; | ||
SwaRoleGuard.prototype.canLoad = function (route) { | ||
var navigation = this.router.getCurrentNavigation(); | ||
var targetUrl = !navigation ? '/' : navigation.extractedUrl.toString(); | ||
return this.ensureHasRouteRoles(route, targetUrl); | ||
}; | ||
SwaRoleGuard.prototype.ensureHasRouteRoles = function (route, targetUrl) { | ||
var _this = this; | ||
var roles = route.data['allowedRoles']; | ||
if (!roles) { | ||
// Q: why are we calling `ensureLoggedIn` below? | ||
// A: Angular will execute CanLoad guards BEFORE CanActivate guards | ||
// Therefore this guard runs BEFORE the AuthGuard. As a consequence, this guard also | ||
// needs to trigger the login flow. | ||
var allowedRoles = SwaRoleGuard.getAllowedRoles(route); | ||
if (!allowedRoles) { | ||
return true; | ||
} | ||
var allowedRoles = Array.isArray(roles) ? roles : [roles]; | ||
return this.authService.hasSomeRoles$(allowedRoles).pipe(operators.map(function (isAuthorized) { return isAuthorized || _this.router.parseUrl(_this.config.unauthorizedRoute); }), operators.take(1)); | ||
var isLoggedIn$ = rxjs.from(this.authService.ensureLoggedIn(targetUrl)); | ||
return isLoggedIn$.pipe(operators.switchMap(function (isLoggedIn) { | ||
if (!isLoggedIn) { | ||
// the user cancelled login prompt | ||
return rxjs.of(false); | ||
} | ||
return _this.ensureHasSomeRoles(allowedRoles); | ||
})); | ||
}; | ||
SwaRoleGuard.prototype.ensureHasSomeRoles = function (allowedRoles) { | ||
var _this = this; | ||
return this.authService | ||
.hasSomeRoles$(allowedRoles) | ||
.pipe(operators.map(function (isAuthorized) { return isAuthorized || _this.router.parseUrl(_this.config.unauthorizedRoute); })); | ||
}; | ||
return SwaRoleGuard; | ||
@@ -1104,0 +1168,0 @@ }()); |
import { Injectable } from '@angular/core'; | ||
import { Router } from '@angular/router'; | ||
import { AuthService } from './auth.service'; | ||
import * as i0 from "@angular/core"; | ||
import * as i1 from "./auth.service"; | ||
import * as i2 from "@angular/router"; | ||
/** | ||
* Add to a route to trigger the sign in flow when the user is not already authenticated | ||
* | ||
* Implements `CanActivate` to ensure the user is authenticated before allowing the navigation to the route. | ||
* Where the user is not yet authenticated, trigger the login flow. | ||
* @see { AuthService.ensureLoggedIn} | ||
* Implements `CanLoad` for use with lazy loaded routes and `CanActivate` for regular routes. | ||
* | ||
* @see { AuthService.ensureLoggedIn } | ||
* @example | ||
* ```ts | ||
* export const routes: Routes = [ | ||
* { path: '', pathMatch: 'full', redirectTo: 'secure-page' }, | ||
* { path: 'secure-page', component: SecurePageComponent, canActivate: [AuthGuard] } | ||
* { path: 'secure-page', component: SecurePageComponent, canActivate: [AuthGuard] }, | ||
* { | ||
* path: 'product', | ||
* canLoad: [AuthGuard], | ||
* loadChildren: () => import('@christianacca/demo-app/product-admin').then(m => m.ProductAdminModule) | ||
* }, | ||
* ]; | ||
@@ -20,4 +26,5 @@ * ``` | ||
export class AuthGuard { | ||
constructor(authService) { | ||
constructor(authService, router) { | ||
this.authService = authService; | ||
this.router = router; | ||
} | ||
@@ -27,4 +34,9 @@ canActivate(_route, state) { | ||
} | ||
canLoad( /* route: Route, segments: UrlSegment[] */) { | ||
const navigation = this.router.getCurrentNavigation(); | ||
const targetUrl = !navigation ? '/' : navigation.extractedUrl.toString(); | ||
return this.authService.ensureLoggedIn(targetUrl); | ||
} | ||
} | ||
AuthGuard.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AuthGuard, deps: [{ token: i1.AuthService }], target: i0.ɵɵFactoryTarget.Injectable }); | ||
AuthGuard.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AuthGuard, deps: [{ token: i1.AuthService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable }); | ||
AuthGuard.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AuthGuard, providedIn: 'root' }); | ||
@@ -36,3 +48,3 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AuthGuard, decorators: [{ | ||
}] | ||
}], ctorParameters: function () { return [{ type: i1.AuthService }]; } }); | ||
}], ctorParameters: function () { return [{ type: i1.AuthService }, { type: i2.Router }]; } }); | ||
//# sourceMappingURL=auth.guard.js.map |
import { __awaiter } from "tslib"; | ||
import { Injectable } from '@angular/core'; | ||
import { defer, of, Subject } from 'rxjs'; | ||
import { first, map, mergeMap, shareReplay, tap } from 'rxjs/operators'; | ||
import { first, map, mergeMap, shareReplay, take, tap } from 'rxjs/operators'; | ||
import { AuthConfig } from './auth-config'; | ||
@@ -30,3 +30,8 @@ import { AuthEvent } from './auth-event'; | ||
*/ | ||
export const hasSomeAllowedRoles = (allowedRoles, actualRoles) => allowedRoles.length === 0 || allowedRoles.includes(anonymousRole) || allowedRoles.some(r => actualRoles.includes(r)); | ||
export const hasSomeAllowedRoles = (allowedRoles, actualRoles) => { | ||
const allowedRoleNames = allowedRoles.flat(10); | ||
return (allowedRoleNames.length === 0 || | ||
allowedRoleNames.includes(anonymousRole) || | ||
allowedRoleNames.some(r => actualRoles.includes(r))); | ||
}; | ||
/** | ||
@@ -50,3 +55,3 @@ * The main service for working with authenticated users | ||
this.sessionEvents$ = this.sessionEvents.asObservable(); | ||
this.userLoaded$ = defer(() => this.httpGet('/.auth/me')).pipe(map(resp => resp.clientPrincipal), tap(user => { | ||
this.currentUser$ = defer(() => this.httpGet('/.auth/me')).pipe(map(resp => resp.clientPrincipal), tap(user => { | ||
if (user) { | ||
@@ -56,4 +61,4 @@ this.publishAuthenticatedSuccessEvents(user); | ||
}), shareReplay({ bufferSize: 1, refCount: false })); | ||
this.isAuthenticated$ = this.userLoaded$.pipe(map(user => !!user), shareReplay({ bufferSize: 1, refCount: false })); | ||
this.currentIdp$ = this.userLoaded$.pipe(map(user => user === null || user === void 0 ? void 0 : user.identityProvider)); | ||
this.isAuthenticated$ = this.currentUser$.pipe(map(user => !!user), shareReplay({ bufferSize: 1, refCount: false })); | ||
this.currentIdp$ = this.currentUser$.pipe(map(user => user === null || user === void 0 ? void 0 : user.identityProvider)); | ||
} | ||
@@ -72,3 +77,3 @@ /** | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const user = yield this.userLoaded$.pipe(first()).toPromise(); | ||
const user = yield this.currentUser$.pipe(first()).toPromise(); | ||
if (user) { | ||
@@ -82,7 +87,11 @@ return true; | ||
/** | ||
* Does the current user have one or more of the `allowedRoles` supplied | ||
* Does the current user have one or more of the `allowedRoles` supplied. | ||
* | ||
* Note: because the observable returned completes, consumers do NOT have to unsubscribe from it | ||
* | ||
* @param allowedRoles The list of roles to check | ||
* @return {Observable<boolean>} an observable that returns true/false and then completes | ||
*/ | ||
hasSomeRoles$(allowedRoles) { | ||
return this.userLoaded$.pipe(map(user => { var _a; return hasSomeAllowedRoles(allowedRoles, (_a = user === null || user === void 0 ? void 0 : user.userRoles) !== null && _a !== void 0 ? _a : noExplicitRoles); })); | ||
return this.currentUser$.pipe(map(user => { var _a; return hasSomeAllowedRoles(allowedRoles, (_a = user === null || user === void 0 ? void 0 : user.userRoles) !== null && _a !== void 0 ? _a : noExplicitRoles); }), take(1)); | ||
} | ||
@@ -117,3 +126,3 @@ /** | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const user = yield this.userLoaded$.toPromise(); | ||
const user = yield this.currentUser$.toPromise(); | ||
if (!user) { | ||
@@ -137,3 +146,3 @@ return false; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const user = yield this.userLoaded$.toPromise(); | ||
const user = yield this.currentUser$.toPromise(); | ||
if (!user) { | ||
@@ -140,0 +149,0 @@ return false; |
import { Injectable } from '@angular/core'; | ||
import { Router } from '@angular/router'; | ||
import { map, take } from 'rxjs/operators'; | ||
import { from, of } from 'rxjs'; | ||
import { map, switchMap } from 'rxjs/operators'; | ||
import { AuthConfig } from './auth-config'; | ||
@@ -13,8 +14,13 @@ import { AuthService } from './auth.service'; | ||
* | ||
* Implements `CanActivate` to verify that the current user is a member of one or more roles | ||
* as defined in an `allowedRoles` field on `Route.data` for the route about to be navigated to | ||
* Implements `CanLoad` for use with lazy loaded routes and `CanActivate` for regular routes. | ||
* | ||
* Will first trigger the sign in flow when the user is not already authenticated. Then verifies | ||
* that the user is a member of one or more {@link AllowedRole}'s as defined in an `allowedRoles` | ||
* field on `Route.data` for the route about to be navigated to. | ||
* | ||
* Where the user is deemed unauthorized the SPA will be routed to the client-side route configured | ||
* using {@link AuthConfig.unauthorizedRoute} | ||
* | ||
* @see {AuthService.hasSomeRoles$} | ||
* | ||
* @example | ||
@@ -24,8 +30,16 @@ * ```ts | ||
* { | ||
* path: 'admin-page', | ||
* path: 'product-admin', | ||
* data: { | ||
* allowedRoles: 'admin' // or ['admin',] | ||
* allowedRoles: 'admin' // other ex: ['admin', 'owner'] ['admin', ['product-reader', 'owner']] | ||
* }, | ||
* canActivate: [SwaRoleGuard], | ||
* component: AdminComponent | ||
* }, | ||
* { | ||
* path: 'user-admin', | ||
* data: { | ||
* allowedRoles: 'owner' | ||
* }, | ||
* canLoad: [SwaRoleGuard], | ||
* loadChildren: () => import('@christianacca/demo-app/user-admin').then(m => m.UserAdminModule) | ||
* } | ||
@@ -41,10 +55,41 @@ * ]; | ||
} | ||
canActivate(route) { | ||
const roles = route.data['allowedRoles']; | ||
static getAllowedRoles(route) { | ||
var _a; | ||
const roles = (_a = route.data) === null || _a === void 0 ? void 0 : _a.allowedRoles; | ||
if (!roles) { | ||
return undefined; | ||
} | ||
return Array.isArray(roles) ? roles : [roles]; | ||
} | ||
canActivate(route, state) { | ||
return this.ensureHasRouteRoles(route, state.url); | ||
} | ||
canLoad(route) { | ||
const navigation = this.router.getCurrentNavigation(); | ||
const targetUrl = !navigation ? '/' : navigation.extractedUrl.toString(); | ||
return this.ensureHasRouteRoles(route, targetUrl); | ||
} | ||
ensureHasRouteRoles(route, targetUrl) { | ||
// Q: why are we calling `ensureLoggedIn` below? | ||
// A: Angular will execute CanLoad guards BEFORE CanActivate guards | ||
// Therefore this guard runs BEFORE the AuthGuard. As a consequence, this guard also | ||
// needs to trigger the login flow. | ||
const allowedRoles = SwaRoleGuard.getAllowedRoles(route); | ||
if (!allowedRoles) { | ||
return true; | ||
} | ||
const allowedRoles = Array.isArray(roles) ? roles : [roles]; | ||
return this.authService.hasSomeRoles$(allowedRoles).pipe(map(isAuthorized => isAuthorized || this.router.parseUrl(this.config.unauthorizedRoute)), take(1)); | ||
const isLoggedIn$ = from(this.authService.ensureLoggedIn(targetUrl)); | ||
return isLoggedIn$.pipe(switchMap(isLoggedIn => { | ||
if (!isLoggedIn) { | ||
// the user cancelled login prompt | ||
return of(false); | ||
} | ||
return this.ensureHasSomeRoles(allowedRoles); | ||
})); | ||
} | ||
ensureHasSomeRoles(allowedRoles) { | ||
return this.authService | ||
.hasSomeRoles$(allowedRoles) | ||
.pipe(map(isAuthorized => isAuthorized || this.router.parseUrl(this.config.unauthorizedRoute))); | ||
} | ||
} | ||
@@ -51,0 +96,0 @@ SwaRoleGuard.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: SwaRoleGuard, deps: [{ token: i1.AuthService }, { token: i2.Router }, { token: i3.AuthConfig }], target: i0.ɵɵFactoryTarget.Injectable }); |
@@ -18,8 +18,8 @@ import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; | ||
* ```html | ||
* <nav class="menu" *swaRoleCheck="let isAdmin of ['admin']; let maybeAdmin = isPlaceholder"> | ||
* <nav class="menu" *swaRoleCheck="let canAdmin of ['admin']; let maybeCanAdmin = isPlaceholder"> | ||
* <p class="menu-label">Menu</p> | ||
* <ul class="menu-list"> | ||
* <a routerLink="/users" routerLinkActive="is-active"> | ||
* <progress *ngIf="maybeAdmin" class="progress is-primary is-medium" max="100">15%</progress> | ||
* <span *ngIf="!maybeAdmin" [ngClass]="!isAdmin ? 'has-text-grey-lighter' : ''">Users</span> | ||
* <progress *ngIf="maybeCanAdmin" class="progress is-primary is-medium" max="100">15%</progress> | ||
* <span *ngIf="!maybeCanAdmin" [ngClass]="!canAdmin ? 'has-text-grey-lighter' : ''">Users</span> | ||
* </a> | ||
@@ -60,3 +60,3 @@ * </ul> | ||
ngOnInit() { | ||
const injectedRoles$ = this.authService.userLoaded$.pipe(map(user => user === null || user === void 0 ? void 0 : user.userRoles), takeUntil(this.userRolesFromTemplate)); | ||
const injectedRoles$ = this.authService.currentUser$.pipe(map(user => user === null || user === void 0 ? void 0 : user.userRoles), takeUntil(this.userRolesFromTemplate)); | ||
const userRoles$ = merge(this.userRolesFromTemplate, injectedRoles$).pipe(map(x => x !== null && x !== void 0 ? x : noExplicitRoles)); | ||
@@ -63,0 +63,0 @@ const permissionCheck$ = combineLatest([this.allowedRoles, userRoles$]).pipe(map(([allowedRoles, userRoles]) => hasSomeAllowedRoles(allowedRoles, userRoles))); |
@@ -5,3 +5,3 @@ import { HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http'; | ||
import { of, Subject, defer, Subscription, EMPTY, from, throwError, ReplaySubject, merge, combineLatest, BehaviorSubject } from 'rxjs'; | ||
import { map, tap, shareReplay, first, mergeMap, concatMap, catchError, takeUntil, take } from 'rxjs/operators'; | ||
import { map, tap, shareReplay, first, take, mergeMap, concatMap, catchError, takeUntil, switchMap } from 'rxjs/operators'; | ||
import { __awaiter } from 'tslib'; | ||
@@ -218,3 +218,8 @@ import * as i2 from '@angular/router'; | ||
*/ | ||
const hasSomeAllowedRoles = (allowedRoles, actualRoles) => allowedRoles.length === 0 || allowedRoles.includes(anonymousRole) || allowedRoles.some(r => actualRoles.includes(r)); | ||
const hasSomeAllowedRoles = (allowedRoles, actualRoles) => { | ||
const allowedRoleNames = allowedRoles.flat(10); | ||
return (allowedRoleNames.length === 0 || | ||
allowedRoleNames.includes(anonymousRole) || | ||
allowedRoleNames.some(r => actualRoles.includes(r))); | ||
}; | ||
/** | ||
@@ -238,3 +243,3 @@ * The main service for working with authenticated users | ||
this.sessionEvents$ = this.sessionEvents.asObservable(); | ||
this.userLoaded$ = defer(() => this.httpGet('/.auth/me')).pipe(map(resp => resp.clientPrincipal), tap(user => { | ||
this.currentUser$ = defer(() => this.httpGet('/.auth/me')).pipe(map(resp => resp.clientPrincipal), tap(user => { | ||
if (user) { | ||
@@ -244,4 +249,4 @@ this.publishAuthenticatedSuccessEvents(user); | ||
}), shareReplay({ bufferSize: 1, refCount: false })); | ||
this.isAuthenticated$ = this.userLoaded$.pipe(map(user => !!user), shareReplay({ bufferSize: 1, refCount: false })); | ||
this.currentIdp$ = this.userLoaded$.pipe(map(user => user === null || user === void 0 ? void 0 : user.identityProvider)); | ||
this.isAuthenticated$ = this.currentUser$.pipe(map(user => !!user), shareReplay({ bufferSize: 1, refCount: false })); | ||
this.currentIdp$ = this.currentUser$.pipe(map(user => user === null || user === void 0 ? void 0 : user.identityProvider)); | ||
} | ||
@@ -260,3 +265,3 @@ /** | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const user = yield this.userLoaded$.pipe(first()).toPromise(); | ||
const user = yield this.currentUser$.pipe(first()).toPromise(); | ||
if (user) { | ||
@@ -270,7 +275,11 @@ return true; | ||
/** | ||
* Does the current user have one or more of the `allowedRoles` supplied | ||
* Does the current user have one or more of the `allowedRoles` supplied. | ||
* | ||
* Note: because the observable returned completes, consumers do NOT have to unsubscribe from it | ||
* | ||
* @param allowedRoles The list of roles to check | ||
* @return {Observable<boolean>} an observable that returns true/false and then completes | ||
*/ | ||
hasSomeRoles$(allowedRoles) { | ||
return this.userLoaded$.pipe(map(user => { var _a; return hasSomeAllowedRoles(allowedRoles, (_a = user === null || user === void 0 ? void 0 : user.userRoles) !== null && _a !== void 0 ? _a : noExplicitRoles$1); })); | ||
return this.currentUser$.pipe(map(user => { var _a; return hasSomeAllowedRoles(allowedRoles, (_a = user === null || user === void 0 ? void 0 : user.userRoles) !== null && _a !== void 0 ? _a : noExplicitRoles$1); }), take(1)); | ||
} | ||
@@ -305,3 +314,3 @@ /** | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const user = yield this.userLoaded$.toPromise(); | ||
const user = yield this.currentUser$.toPromise(); | ||
if (!user) { | ||
@@ -325,3 +334,3 @@ return false; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const user = yield this.userLoaded$.toPromise(); | ||
const user = yield this.currentUser$.toPromise(); | ||
if (!user) { | ||
@@ -498,8 +507,8 @@ return false; | ||
* ```html | ||
* <nav class="menu" *swaRoleCheck="let isAdmin of ['admin']; let maybeAdmin = isPlaceholder"> | ||
* <nav class="menu" *swaRoleCheck="let canAdmin of ['admin']; let maybeCanAdmin = isPlaceholder"> | ||
* <p class="menu-label">Menu</p> | ||
* <ul class="menu-list"> | ||
* <a routerLink="/users" routerLinkActive="is-active"> | ||
* <progress *ngIf="maybeAdmin" class="progress is-primary is-medium" max="100">15%</progress> | ||
* <span *ngIf="!maybeAdmin" [ngClass]="!isAdmin ? 'has-text-grey-lighter' : ''">Users</span> | ||
* <progress *ngIf="maybeCanAdmin" class="progress is-primary is-medium" max="100">15%</progress> | ||
* <span *ngIf="!maybeCanAdmin" [ngClass]="!canAdmin ? 'has-text-grey-lighter' : ''">Users</span> | ||
* </a> | ||
@@ -540,3 +549,3 @@ * </ul> | ||
ngOnInit() { | ||
const injectedRoles$ = this.authService.userLoaded$.pipe(map(user => user === null || user === void 0 ? void 0 : user.userRoles), takeUntil(this.userRolesFromTemplate)); | ||
const injectedRoles$ = this.authService.currentUser$.pipe(map(user => user === null || user === void 0 ? void 0 : user.userRoles), takeUntil(this.userRolesFromTemplate)); | ||
const userRoles$ = merge(this.userRolesFromTemplate, injectedRoles$).pipe(map(x => x !== null && x !== void 0 ? x : noExplicitRoles)); | ||
@@ -616,10 +625,14 @@ const permissionCheck$ = combineLatest([this.allowedRoles, userRoles$]).pipe(map(([allowedRoles, userRoles]) => hasSomeAllowedRoles(allowedRoles, userRoles))); | ||
* | ||
* Implements `CanActivate` to ensure the user is authenticated before allowing the navigation to the route. | ||
* Where the user is not yet authenticated, trigger the login flow. | ||
* @see { AuthService.ensureLoggedIn} | ||
* Implements `CanLoad` for use with lazy loaded routes and `CanActivate` for regular routes. | ||
* | ||
* @see { AuthService.ensureLoggedIn } | ||
* @example | ||
* ```ts | ||
* export const routes: Routes = [ | ||
* { path: '', pathMatch: 'full', redirectTo: 'secure-page' }, | ||
* { path: 'secure-page', component: SecurePageComponent, canActivate: [AuthGuard] } | ||
* { path: 'secure-page', component: SecurePageComponent, canActivate: [AuthGuard] }, | ||
* { | ||
* path: 'product', | ||
* canLoad: [AuthGuard], | ||
* loadChildren: () => import('@christianacca/demo-app/product-admin').then(m => m.ProductAdminModule) | ||
* }, | ||
* ]; | ||
@@ -629,4 +642,5 @@ * ``` | ||
class AuthGuard { | ||
constructor(authService) { | ||
constructor(authService, router) { | ||
this.authService = authService; | ||
this.router = router; | ||
} | ||
@@ -636,4 +650,9 @@ canActivate(_route, state) { | ||
} | ||
canLoad( /* route: Route, segments: UrlSegment[] */) { | ||
const navigation = this.router.getCurrentNavigation(); | ||
const targetUrl = !navigation ? '/' : navigation.extractedUrl.toString(); | ||
return this.authService.ensureLoggedIn(targetUrl); | ||
} | ||
} | ||
AuthGuard.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AuthGuard, deps: [{ token: AuthService }], target: i0.ɵɵFactoryTarget.Injectable }); | ||
AuthGuard.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AuthGuard, deps: [{ token: AuthService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable }); | ||
AuthGuard.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AuthGuard, providedIn: 'root' }); | ||
@@ -645,3 +664,3 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AuthGuard, decorators: [{ | ||
}] | ||
}], ctorParameters: function () { return [{ type: AuthService }]; } }); | ||
}], ctorParameters: function () { return [{ type: AuthService }, { type: i2.Router }]; } }); | ||
@@ -651,8 +670,13 @@ /** | ||
* | ||
* Implements `CanActivate` to verify that the current user is a member of one or more roles | ||
* as defined in an `allowedRoles` field on `Route.data` for the route about to be navigated to | ||
* Implements `CanLoad` for use with lazy loaded routes and `CanActivate` for regular routes. | ||
* | ||
* Will first trigger the sign in flow when the user is not already authenticated. Then verifies | ||
* that the user is a member of one or more {@link AllowedRole}'s as defined in an `allowedRoles` | ||
* field on `Route.data` for the route about to be navigated to. | ||
* | ||
* Where the user is deemed unauthorized the SPA will be routed to the client-side route configured | ||
* using {@link AuthConfig.unauthorizedRoute} | ||
* | ||
* @see {AuthService.hasSomeRoles$} | ||
* | ||
* @example | ||
@@ -662,8 +686,16 @@ * ```ts | ||
* { | ||
* path: 'admin-page', | ||
* path: 'product-admin', | ||
* data: { | ||
* allowedRoles: 'admin' // or ['admin',] | ||
* allowedRoles: 'admin' // other ex: ['admin', 'owner'] ['admin', ['product-reader', 'owner']] | ||
* }, | ||
* canActivate: [SwaRoleGuard], | ||
* component: AdminComponent | ||
* }, | ||
* { | ||
* path: 'user-admin', | ||
* data: { | ||
* allowedRoles: 'owner' | ||
* }, | ||
* canLoad: [SwaRoleGuard], | ||
* loadChildren: () => import('@christianacca/demo-app/user-admin').then(m => m.UserAdminModule) | ||
* } | ||
@@ -679,10 +711,41 @@ * ]; | ||
} | ||
canActivate(route) { | ||
const roles = route.data['allowedRoles']; | ||
static getAllowedRoles(route) { | ||
var _a; | ||
const roles = (_a = route.data) === null || _a === void 0 ? void 0 : _a.allowedRoles; | ||
if (!roles) { | ||
return undefined; | ||
} | ||
return Array.isArray(roles) ? roles : [roles]; | ||
} | ||
canActivate(route, state) { | ||
return this.ensureHasRouteRoles(route, state.url); | ||
} | ||
canLoad(route) { | ||
const navigation = this.router.getCurrentNavigation(); | ||
const targetUrl = !navigation ? '/' : navigation.extractedUrl.toString(); | ||
return this.ensureHasRouteRoles(route, targetUrl); | ||
} | ||
ensureHasRouteRoles(route, targetUrl) { | ||
// Q: why are we calling `ensureLoggedIn` below? | ||
// A: Angular will execute CanLoad guards BEFORE CanActivate guards | ||
// Therefore this guard runs BEFORE the AuthGuard. As a consequence, this guard also | ||
// needs to trigger the login flow. | ||
const allowedRoles = SwaRoleGuard.getAllowedRoles(route); | ||
if (!allowedRoles) { | ||
return true; | ||
} | ||
const allowedRoles = Array.isArray(roles) ? roles : [roles]; | ||
return this.authService.hasSomeRoles$(allowedRoles).pipe(map(isAuthorized => isAuthorized || this.router.parseUrl(this.config.unauthorizedRoute)), take(1)); | ||
const isLoggedIn$ = from(this.authService.ensureLoggedIn(targetUrl)); | ||
return isLoggedIn$.pipe(switchMap(isLoggedIn => { | ||
if (!isLoggedIn) { | ||
// the user cancelled login prompt | ||
return of(false); | ||
} | ||
return this.ensureHasSomeRoles(allowedRoles); | ||
})); | ||
} | ||
ensureHasSomeRoles(allowedRoles) { | ||
return this.authService | ||
.hasSomeRoles$(allowedRoles) | ||
.pipe(map(isAuthorized => isAuthorized || this.router.parseUrl(this.config.unauthorizedRoute))); | ||
} | ||
} | ||
@@ -689,0 +752,0 @@ SwaRoleGuard.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: SwaRoleGuard, deps: [{ token: AuthService }, { token: i2.Router }, { token: AuthConfig }], target: i0.ɵɵFactoryTarget.Injectable }); |
@@ -1,3 +0,2 @@ | ||
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router'; | ||
import { Observable } from 'rxjs'; | ||
import { ActivatedRouteSnapshot, CanActivate, CanLoad, Router, RouterStateSnapshot } from '@angular/router'; | ||
import { AuthService } from './auth.service'; | ||
@@ -8,19 +7,25 @@ import * as i0 from "@angular/core"; | ||
* | ||
* Implements `CanActivate` to ensure the user is authenticated before allowing the navigation to the route. | ||
* Where the user is not yet authenticated, trigger the login flow. | ||
* @see { AuthService.ensureLoggedIn} | ||
* Implements `CanLoad` for use with lazy loaded routes and `CanActivate` for regular routes. | ||
* | ||
* @see { AuthService.ensureLoggedIn } | ||
* @example | ||
* ```ts | ||
* export const routes: Routes = [ | ||
* { path: '', pathMatch: 'full', redirectTo: 'secure-page' }, | ||
* { path: 'secure-page', component: SecurePageComponent, canActivate: [AuthGuard] } | ||
* { path: 'secure-page', component: SecurePageComponent, canActivate: [AuthGuard] }, | ||
* { | ||
* path: 'product', | ||
* canLoad: [AuthGuard], | ||
* loadChildren: () => import('@christianacca/demo-app/product-admin').then(m => m.ProductAdminModule) | ||
* }, | ||
* ]; | ||
* ``` | ||
*/ | ||
export declare class AuthGuard implements CanActivate { | ||
export declare class AuthGuard implements CanActivate, CanLoad { | ||
private authService; | ||
constructor(authService: AuthService); | ||
canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree; | ||
private router; | ||
constructor(authService: AuthService, router: Router); | ||
canActivate(_route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean>; | ||
canLoad(): Promise<boolean>; | ||
static ɵfac: i0.ɵɵFactoryDeclaration<AuthGuard, never>; | ||
static ɵprov: i0.ɵɵInjectableDeclaration<AuthGuard>; | ||
} |
@@ -8,2 +8,3 @@ import { Observable, Subject } from 'rxjs'; | ||
import * as i0 from "@angular/core"; | ||
export declare type AllowedRole = string | AllowedRole[]; | ||
/** | ||
@@ -50,3 +51,3 @@ * Options that control the behaviour when purging user information | ||
*/ | ||
export declare const hasSomeAllowedRoles: (allowedRoles: string[], actualRoles: string[]) => boolean; | ||
export declare const hasSomeAllowedRoles: (allowedRoles: AllowedRole[], actualRoles: string[]) => boolean; | ||
/** | ||
@@ -60,2 +61,10 @@ * The main service for working with authenticated users | ||
/** | ||
* Return the current authenticated user or `null` when the user is not authenticated. | ||
* | ||
* The first subscriber will trigger a fetch from the built-in user api endpoint. Late subscribers will then receive | ||
* the last value emitted. | ||
* | ||
*/ | ||
currentUser$: Observable<ClientPrincipal | null>; | ||
/** | ||
* The identity providers available to login with. | ||
@@ -78,10 +87,2 @@ * Note: This is just a convenient alias of `AuthConfig.identityProviders` | ||
sessionEvents$: Observable<AuthEvent>; | ||
/** | ||
* An event that will emit user details is fetched from the api. The value emitted will | ||
* be undefined when the user is not authenticated | ||
* | ||
* Late subscribers will receive the last value emitted. | ||
* | ||
*/ | ||
userLoaded$: Observable<ClientPrincipal | null>; | ||
private currentIdp$; | ||
@@ -101,6 +102,10 @@ constructor(config: AuthConfig, storage: StorageService, idpSelectorService: IdentityProviderSelectorService); | ||
/** | ||
* Does the current user have one or more of the `allowedRoles` supplied | ||
* Does the current user have one or more of the `allowedRoles` supplied. | ||
* | ||
* Note: because the observable returned completes, consumers do NOT have to unsubscribe from it | ||
* | ||
* @param allowedRoles The list of roles to check | ||
* @return {Observable<boolean>} an observable that returns true/false and then completes | ||
*/ | ||
hasSomeRoles$(allowedRoles: string[]): Observable<boolean>; | ||
hasSomeRoles$(allowedRoles: AllowedRole[]): Observable<boolean>; | ||
/** | ||
@@ -107,0 +112,0 @@ * Trigger the login flow, redirecting the browser to the identity provider. |
@@ -1,2 +0,2 @@ | ||
import { ActivatedRouteSnapshot, CanActivate, Router, UrlTree } from '@angular/router'; | ||
import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; | ||
import { Observable } from 'rxjs'; | ||
@@ -9,8 +9,13 @@ import { AuthConfig } from './auth-config'; | ||
* | ||
* Implements `CanActivate` to verify that the current user is a member of one or more roles | ||
* as defined in an `allowedRoles` field on `Route.data` for the route about to be navigated to | ||
* Implements `CanLoad` for use with lazy loaded routes and `CanActivate` for regular routes. | ||
* | ||
* Will first trigger the sign in flow when the user is not already authenticated. Then verifies | ||
* that the user is a member of one or more {@link AllowedRole}'s as defined in an `allowedRoles` | ||
* field on `Route.data` for the route about to be navigated to. | ||
* | ||
* Where the user is deemed unauthorized the SPA will be routed to the client-side route configured | ||
* using {@link AuthConfig.unauthorizedRoute} | ||
* | ||
* @see {AuthService.hasSomeRoles$} | ||
* | ||
* @example | ||
@@ -20,8 +25,16 @@ * ```ts | ||
* { | ||
* path: 'admin-page', | ||
* path: 'product-admin', | ||
* data: { | ||
* allowedRoles: 'admin' // or ['admin',] | ||
* allowedRoles: 'admin' // other ex: ['admin', 'owner'] ['admin', ['product-reader', 'owner']] | ||
* }, | ||
* canActivate: [SwaRoleGuard], | ||
* component: AdminComponent | ||
* }, | ||
* { | ||
* path: 'user-admin', | ||
* data: { | ||
* allowedRoles: 'owner' | ||
* }, | ||
* canLoad: [SwaRoleGuard], | ||
* loadChildren: () => import('@christianacca/demo-app/user-admin').then(m => m.UserAdminModule) | ||
* } | ||
@@ -31,3 +44,3 @@ * ]; | ||
*/ | ||
export declare class SwaRoleGuard implements CanActivate { | ||
export declare class SwaRoleGuard implements CanActivate, CanLoad { | ||
private authService; | ||
@@ -37,5 +50,9 @@ private router; | ||
constructor(authService: AuthService, router: Router, config: AuthConfig); | ||
canActivate(route: ActivatedRouteSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree; | ||
private static getAllowedRoles; | ||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean | UrlTree>; | ||
canLoad(route: Route): boolean | Observable<boolean | UrlTree>; | ||
private ensureHasRouteRoles; | ||
private ensureHasSomeRoles; | ||
static ɵfac: i0.ɵɵFactoryDeclaration<SwaRoleGuard, never>; | ||
static ɵprov: i0.ɵɵInjectableDeclaration<SwaRoleGuard>; | ||
} |
import { OnDestroy, OnInit, TemplateRef, ViewContainerRef } from '@angular/core'; | ||
import { AuthService } from './auth.service'; | ||
import { AllowedRole, AuthService } from './auth.service'; | ||
import * as i0 from "@angular/core"; | ||
@@ -11,8 +11,8 @@ /** | ||
* ```html | ||
* <nav class="menu" *swaRoleCheck="let isAdmin of ['admin']; let maybeAdmin = isPlaceholder"> | ||
* <nav class="menu" *swaRoleCheck="let canAdmin of ['admin']; let maybeCanAdmin = isPlaceholder"> | ||
* <p class="menu-label">Menu</p> | ||
* <ul class="menu-list"> | ||
* <a routerLink="/users" routerLinkActive="is-active"> | ||
* <progress *ngIf="maybeAdmin" class="progress is-primary is-medium" max="100">15%</progress> | ||
* <span *ngIf="!maybeAdmin" [ngClass]="!isAdmin ? 'has-text-grey-lighter' : ''">Users</span> | ||
* <progress *ngIf="maybeCanAdmin" class="progress is-primary is-medium" max="100">15%</progress> | ||
* <span *ngIf="!maybeCanAdmin" [ngClass]="!canAdmin ? 'has-text-grey-lighter' : ''">Users</span> | ||
* </a> | ||
@@ -27,3 +27,3 @@ * </ul> | ||
private authService; | ||
set swaRoleCheckOf(value: string[]); | ||
set swaRoleCheckOf(value: AllowedRole[]); | ||
set swaRoleCheckUserRoles(value: string[]); | ||
@@ -30,0 +30,0 @@ private allowedRoles; |
{ | ||
"name": "@christianacca/angular-swa-auth", | ||
"description": "Programmatically work with Azure Static Web Apps authentication in an angular app", | ||
"version": "1.1.2", | ||
"version": "2.0.0-beta.1", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "azure", |
@@ -142,4 +142,29 @@ # @christianacca/angular-swa-auth | ||
``` | ||
4. Optionally add `SwaRoleGuard` to your route(s) | ||
```ts | ||
import { AuthGuard } from '@christianacca/angular-swa-auth'; | ||
4. Optionally send authentication session events to your function app api | ||
const routes: Route[] = [ | ||
{ | ||
path: 'product-admin', | ||
data: { | ||
allowedRoles: 'admin' // other ex: ['admin', 'owner'] ['admin', ['product-reader', 'owner']] | ||
}, | ||
canActivate: [SwaRoleGuard], | ||
component: AdminComponent | ||
}, | ||
{ | ||
path: 'user-admin', | ||
data: { | ||
allowedRoles: 'owner' | ||
}, | ||
canLoad: [SwaRoleGuard], | ||
loadChildren: () => import('@christianacca/demo-app/user-admin').then(m => m.UserAdminModule) | ||
} | ||
]; | ||
``` | ||
5. Optionally send authentication session events to your function app api | ||
@@ -146,0 +171,0 @@ ```ts |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
361033
3616
195
2