@rxap/authorization
Version:
Provides an Angular module and directives to manage authorization and permissions in your application. It allows you to control the visibility and enabled state of UI elements based on user permissions. The package includes an `AuthorizationService` to ch
916 lines (750 loc) • 34.2 kB
HTML
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>angular-authorization</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="../images/favicon.ico">
<link rel="stylesheet" href="../styles/style.css">
<link rel="stylesheet" href="../styles/dark.css">
</head>
<body>
<script>
// Blocking script to avoid flickering dark mode
// Dark mode toggle button
var useDark = window.matchMedia('(prefers-color-scheme: dark)');
var darkModeState = useDark.matches;
var $darkModeToggleSwitchers = document.querySelectorAll('.dark-mode-switch input');
var $darkModeToggles = document.querySelectorAll('.dark-mode-switch');
var darkModeStateLocal = localStorage.getItem('compodoc_darkmode-state');
function checkToggle(check) {
for (var i = 0; i < $darkModeToggleSwitchers.length; i++) {
$darkModeToggleSwitchers[i].checked = check;
}
}
function toggleDarkMode(state) {
if (window.localStorage) {
localStorage.setItem('compodoc_darkmode-state', state);
}
checkToggle(state);
const hasClass = document.body.classList.contains('dark');
if (state) {
for (var i = 0; i < $darkModeToggles.length; i++) {
$darkModeToggles[i].classList.add('dark');
}
if (!hasClass) {
document.body.classList.add('dark');
}
} else {
for (var i = 0; i < $darkModeToggles.length; i++) {
$darkModeToggles[i].classList.remove('dark');
}
if (hasClass) {
document.body.classList.remove('dark');
}
}
}
useDark.addEventListener('change', function (evt) {
toggleDarkMode(evt.matches);
});
if (darkModeStateLocal) {
darkModeState = darkModeStateLocal === 'true';
}
toggleDarkMode(darkModeState);
</script>
<div class="navbar navbar-default navbar-fixed-top d-md-none p-0">
<div class="d-flex">
<a href="../" class="navbar-brand">angular-authorization</a>
<button type="button" class="btn btn-default btn-menu ion-ios-menu" id="btn-menu"></button>
</div>
</div>
<div class="xs-menu menu" id="mobile-menu">
<div id="book-search-input" role="search"><input type="text" placeholder="Type to search"></div> <compodoc-menu></compodoc-menu>
</div>
<div class="container-fluid main">
<div class="row main">
<div class="d-none d-md-block menu">
<compodoc-menu mode="normal"></compodoc-menu>
</div>
<!-- START CONTENT -->
<div class="content injectable">
<div class="content-data">
<ol class="breadcrumb">
<li class="breadcrumb-item">Injectables</li>
<li class="breadcrumb-item" >AuthorizationService</li>
</ol>
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a href="#info"
class="nav-link"
class="nav-link active"
role="tab" id="info-tab" data-bs-toggle="tab" data-link="info">Info</a>
</li>
<li class="nav-item">
<a href="#source"
class="nav-link"
role="tab" id="source-tab" data-bs-toggle="tab" data-link="source">Source</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade active in" id="info">
<p class="comment">
<h3>File</h3>
</p>
<p class="comment">
<code>src/lib/authorization.service.ts</code>
</p>
<section data-compodoc="block-index">
<h3 id="index">Index</h3>
<table class="table table-sm table-bordered index-table">
<tbody>
<tr>
<td class="col-md-4">
<h6><b>Properties</b></h6>
</td>
</tr>
<tr>
<td class="col-md-4">
<ul class="index-list">
<li>
<span class="modifier">Public</span>
<span class="modifier">Readonly</span>
<a href="#disabled" >disabled</a>
</li>
<li>
<span class="modifier">Protected</span>
<span class="modifier">Readonly</span>
<a href="#permissions$" >permissions$</a>
</li>
</ul>
</td>
</tr>
<tr>
<td class="col-md-4">
<h6><b>Methods</b></h6>
</td>
</tr>
<tr>
<td class="col-md-4">
<ul class="index-list">
<li>
<span class="modifier">Public</span>
<a href="#checkPermission" >checkPermission</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#getPermissions" >getPermissions</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#getPermissions$" >getPermissions$</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#hasPermission" >hasPermission</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#hasPermission$" >hasPermission$</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#setPermissions" >setPermissions</a>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</section>
<section data-compodoc="block-methods">
<h3 id="methods">
Methods
</h3>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="checkPermission"></a>
<span class="name">
<span class="modifier">Public</span>
<span ><b>checkPermission</b></span>
<a href="#checkPermission"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>checkPermission(identifier: string | string[], permissions: string[], scope?: string | null)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="28"
class="link-to-prism">src/lib/authorization.service.ts:28</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
</tr>
</thead>
<tbody>
<tr>
<td>identifier</td>
<td>
<code>string | string[]</code>
</td>
<td>
No
</td>
</tr>
<tr>
<td>permissions</td>
<td>
<code>string[]</code>
</td>
<td>
No
</td>
</tr>
<tr>
<td>scope</td>
<td>
<code>string | null</code>
</td>
<td>
Yes
</td>
</tr>
</tbody>
</table>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/boolean" target="_blank" >boolean</a></code>
</div>
<div class="io-description">
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="getPermissions"></a>
<span class="name">
<span class="modifier">Public</span>
<span ><b>getPermissions</b></span>
<a href="#getPermissions"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>getPermissions()</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="130"
class="link-to-prism">src/lib/authorization.service.ts:130</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description">
<b>Returns : </b> <code>string[]</code>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="getPermissions$"></a>
<span class="name">
<span class="modifier">Public</span>
<span ><b>getPermissions$</b></span>
<a href="#getPermissions$"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>getPermissions$()</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="126"
class="link-to-prism">src/lib/authorization.service.ts:126</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description">
<b>Returns : </b> <code>Observable<string[]></code>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="hasPermission"></a>
<span class="name">
<span class="modifier">Public</span>
<span ><b>hasPermission</b></span>
<a href="#hasPermission"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>hasPermission(identifier: string | string[], scope?: string | null, ignorePermissionList?: string[])</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="113"
class="link-to-prism">src/lib/authorization.service.ts:113</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
</tr>
</thead>
<tbody>
<tr>
<td>identifier</td>
<td>
<code>string | string[]</code>
</td>
<td>
No
</td>
</tr>
<tr>
<td>scope</td>
<td>
<code>string | null</code>
</td>
<td>
Yes
</td>
</tr>
<tr>
<td>ignorePermissionList</td>
<td>
<code>string[]</code>
</td>
<td>
Yes
</td>
</tr>
</tbody>
</table>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/boolean" target="_blank" >boolean</a></code>
</div>
<div class="io-description">
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="hasPermission$"></a>
<span class="name">
<span class="modifier">Public</span>
<span ><b>hasPermission$</b></span>
<a href="#hasPermission$"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>hasPermission$(identifier: string | string[], scope?: string | null, ignorePermissionList?: string[])</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="97"
class="link-to-prism">src/lib/authorization.service.ts:97</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
</tr>
</thead>
<tbody>
<tr>
<td>identifier</td>
<td>
<code>string | string[]</code>
</td>
<td>
No
</td>
</tr>
<tr>
<td>scope</td>
<td>
<code>string | null</code>
</td>
<td>
Yes
</td>
</tr>
<tr>
<td>ignorePermissionList</td>
<td>
<code>string[]</code>
</td>
<td>
Yes
</td>
</tr>
</tbody>
</table>
</div>
<div class="io-description">
<b>Returns : </b> <code>Observable<boolean></code>
</div>
<div class="io-description">
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="setPermissions"></a>
<span class="name">
<span class="modifier">Public</span>
<span ><b>setPermissions</b></span>
<a href="#setPermissions"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="modifier-icon icon ion-ios-reset"></span>
<code>setPermissions(permissions: string[])</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="24"
class="link-to-prism">src/lib/authorization.service.ts:24</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
</tr>
</thead>
<tbody>
<tr>
<td>permissions</td>
<td>
<code>string[]</code>
</td>
<td>
No
</td>
</tr>
</tbody>
</table>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="https://www.typescriptlang.org/docs/handbook/basic-types.html" target="_blank" >void</a></code>
</div>
<div class="io-description">
</div>
</td>
</tr>
</tbody>
</table>
</section>
<section data-compodoc="block-properties">
<h3 id="inputs">
Properties
</h3>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="disabled"></a>
<span class="name">
<span class="modifier">Public</span>
<span class="modifier">Readonly</span>
<span ><b>disabled</b></span>
<a href="#disabled"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<i>Default value : </i><code>inject(RXAP_DISABLE_AUTHORIZATION, { optional: true }) ?? false</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="22" class="link-to-prism">src/lib/authorization.service.ts:22</a></div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="permissions$"></a>
<span class="name">
<span class="modifier">Protected</span>
<span class="modifier">Readonly</span>
<span ><b>permissions$</b></span>
<a href="#permissions$"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<i>Default value : </i><code>new BehaviorSubject<string[]>([])</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="20" class="link-to-prism">src/lib/authorization.service.ts:20</a></div>
</td>
</tr>
</tbody>
</table>
</section>
</div>
<div class="tab-pane fade tab-source-code" id="source">
<pre class="line-numbers compodoc-sourcecode"><code class="language-typescript">import {
inject,
Injectable,
isDevMode,
} from '@angular/core';
import { coerceArray } from '@rxap/utilities';
import {
BehaviorSubject,
Observable,
} from 'rxjs';
import {
distinctUntilChanged,
map,
} from 'rxjs/operators';
import { RXAP_DISABLE_AUTHORIZATION } from './tokens';
@Injectable({ providedIn: 'root' })
export class AuthorizationService {
protected readonly permissions$ = new BehaviorSubject<string[]>([]);
public readonly disabled = inject(RXAP_DISABLE_AUTHORIZATION, { optional: true }) ?? false;
public setPermissions(permissions: string[]): void {
this.permissions$.next(permissions);
}
public checkPermission(
identifier: string | string[],
permissions: string[],
scope?: string | null,
): boolean {
if (this.disabled) {
console.warn('Authorization is disabled! Granting all permissions!');
return true;
}
identifier = coerceArray(identifier);
if (!identifier.length) {
return true;
}
if (isDevMode()) {
console.log(
`check permission for [${ identifier.join(', ') }]${ scope ? ` with scope '${ scope }': ` : ' :' }`,
permissions,
);
}
// holds all permission, but if a scope is defined only permissions without scope
// or with the matching scope and the scope prefix is removed
let permissionSubset = permissions;
if (scope) {
permissionSubset = permissions
.filter(
(permission) =>
!permission.match(/\//) ||
permission.match(new RegExp(`^${ scope.replace('.', '\\.') }/`)),
).map((permission) =>
permission.replace(
new RegExp(`^${ scope.replace('.', '\\.') }/`),
'',
),
).sort((a, b) => a.length - b.length);
}
if (identifier.every(id => permissionSubset.includes(id))) {
return true;
}
const permissionRegexList = permissionSubset.map((permission) => {
const permissionRegex = permission
.replace('.', '\\.')
.replace('*', '.+');
if (permission[0] === '*' && permission[permission.length - 1] === '*') {
return new RegExp(permissionRegex);
} else if (permission[0] === '*') {
return new RegExp(`${ permissionRegex }$`);
} else if (permission[permission.length - 1] === '*') {
return new RegExp(`^${ permissionRegex }`);
} else {
return new RegExp(`^${ permissionRegex }$`);
}
});
return identifier.every(id => permissionRegexList.some((permissionRegex) =>
id.match(permissionRegex),
));
}
public hasPermission$(
identifier: string | string[],
scope?: string | null,
ignorePermissionList?: string[],
): Observable<boolean> {
return this.permissions$.pipe(
map((permissions) => ignorePermissionList ?
permissions.filter((permission) => !ignorePermissionList.includes(permission)) :
permissions.slice()),
map((permissions) =>
this.checkPermission(identifier, permissions, scope),
),
distinctUntilChanged(),
);
}
public hasPermission(
identifier: string | string[],
scope?: string | null,
ignorePermissionList?: string[],
): boolean {
const allPermissions = this.getPermissions();
const permissions = ignorePermissionList ?
allPermissions.filter((permission) => !ignorePermissionList.includes(permission)) :
allPermissions;
return this.checkPermission(identifier, permissions, scope);
}
public getPermissions$(): Observable<string[]> {
return this.permissions$.asObservable().pipe(map(permissions => permissions.slice()));
}
public getPermissions(): string[] {
return this.permissions$.value.slice();
}
}
</code></pre>
</div>
</div>
</div><div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>
<!-- END CONTENT -->
</div>
</div>
<label class="dark-mode-switch">
<input type="checkbox">
<span class="slider">
<svg class="slider-icon" viewBox="0 0 24 24" fill="none" height="20" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" width="20" xmlns="http://www.w3.org/2000/svg">
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path>
</svg>
</span>
</label>
<script>
var COMPODOC_CURRENT_PAGE_DEPTH = 1;
var COMPODOC_CURRENT_PAGE_CONTEXT = 'injectable';
var COMPODOC_CURRENT_PAGE_URL = 'AuthorizationService.html';
var MAX_SEARCH_RESULTS = 15;
</script>
<script>
$darkModeToggleSwitchers = document.querySelectorAll('.dark-mode-switch input');
checkToggle(darkModeState);
if ($darkModeToggleSwitchers.length > 0) {
for (var i = 0; i < $darkModeToggleSwitchers.length; i++) {
$darkModeToggleSwitchers[i].addEventListener('change', function (event) {
darkModeState = !darkModeState;
toggleDarkMode(darkModeState);
});
}
}
</script>
<script src="../js/libs/custom-elements.min.js"></script>
<script src="../js/libs/lit-html.js"></script>
<script src="../js/menu-wc.js" defer></script>
<script nomodule src="../js/menu-wc_es5.js" defer></script>
<script src="../js/libs/bootstrap-native.js"></script>
<script src="../js/libs/es6-shim.min.js"></script>
<script src="../js/libs/EventDispatcher.js"></script>
<script src="../js/libs/promise.min.js"></script>
<script src="../js/libs/zepto.min.js"></script>
<script src="../js/compodoc.js"></script>
<script src="../js/tabs.js"></script>
<script src="../js/menu.js"></script>
<script src="../js/libs/clipboard.min.js"></script>
<script src="../js/libs/prism.js"></script>
<script src="../js/sourceCode.js"></script>
<script src="../js/search/search.js"></script>
<script src="../js/search/lunr.min.js"></script>
<script src="../js/search/search-lunr.js"></script>
<script src="../js/search/search_index.js"></script>
<script src="../js/lazy-load-graphs.js"></script>
</body>
</html>