@superawesome/permissions
Version:
Fine grained permissions / access control with ownerships & attribute picking, done right.
1,081 lines (940 loc) • 74.9 kB
HTML
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>SuperAwesome Permissions (@superawesome/permissions)</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/postmark.css">
</head>
<body>
<div class="navbar navbar-default navbar-fixed-top visible-xs">
<a href="../" class="navbar-brand">SuperAwesome Permissions (@superawesome/permissions)</a>
<button type="button" class="btn btn-default btn-menu ion-ios-menu" id="btn-menu"></button>
</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="hidden-xs menu">
<compodoc-menu mode="normal"></compodoc-menu>
</div>
<!-- START CONTENT -->
<div class="content class">
<div class="content-data">
<ol class="breadcrumb">
<li>Classes</li>
<li>Permit</li>
</ol>
<ul class="nav nav-tabs" role="tablist">
<li class="active">
<a href="#info" role="tab" id="info-tab" data-toggle="tab" data-link="info">Info</a>
</li>
<li >
<a href="#source" role="tab" id="source-tab" data-toggle="tab" data-link="source">Source</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade active in" id="c-info">
<p class="comment">
<h3>File</h3>
</p>
<p class="comment">
<code>src/Permit.class.ts</code>
</p>
<p class="comment">
<h3>Description</h3>
</p>
<p class="comment">
<p>An <code>Permit</code> instance represents the granted permissions for the current <strong>User</strong> against a <strong>Resource</strong>, <strong>Action</strong> & optionally <strong>resourceId</strong>, along with useful helpers, for async attribute picking, ownership filtering, mapping etc.</p>
<p>Its the result of the evaluation of <a href="/classes/Permissions.html#grantPermit"><code>grantPermit()</code></a>, by applying the User to the PDs.</p>
<p>All the information, helpers & further querying you might require for your current request, you'll find it here.</p>
<p><strong>Note</strong>: <code>Permit</code> constructor is private, you shouldn't instantiate one your self, just call <code>grantPermit()</code>.</p>
</p>
<section>
<h3 id="index">Index</h3>
<table class="table table-sm table-bordered index-table">
<tbody>
<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>
<span class="modifier">Async</span>
<a href="#attributes">attributes</a>
</li>
<li>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
<a href="#filterPick">filterPick</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#isListOwnSupported">isListOwnSupported</a>
</li>
<li>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
<a href="#isOwn">isOwn</a>
</li>
<li>
<span class="modifier">Public</span>
<a href="#limitOwn">limitOwn</a>
</li>
<li>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
<a href="#listOwn">listOwn</a>
</li>
<li>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
<a href="#mapPick">mapPick</a>
</li>
<li>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
<a href="#pick">pick</a>
</li>
</ul>
</td>
</tr>
<tr>
<td class="col-md-4">
<h6><b>Accessors</b></h6>
</td>
</tr>
<tr>
<td class="col-md-4">
<ul class="index-list">
<li>
<a href="#anyGranted">anyGranted</a>
</li>
<li>
<a href="#ownGranted">ownGranted</a>
</li>
<li>
<a href="#anyAttributes">anyAttributes</a>
</li>
<li>
<a href="#ownAttributes">ownAttributes</a>
</li>
<li>
<a href="#granted">granted</a>
</li>
<li>
<a href="#grantedAction">grantedAction</a>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</section>
<section>
<h3 id="methods">
Methods
</h3>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="attributes"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
attributes
</b>
<a href="#attributes"><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>attributes(resourceId?: TResourceId)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="318"
class="link-to-prism">src/Permit.class.ts:318</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Helper that returns the attributes the <strong>User</strong> is permitted to use for the current <strong>Resource</strong> & <strong>Action</strong>.</p>
<p>By optionally passing a <code>resourceId</code> of a particular resource item, we get the effective <code>anyAttributes</code> OR <code>ownAttributes</code> that the particular User, depending on the <strong>ownership of the <code>resourceId</code></strong>, according to this Permit's <code>isOwner</code> result.</p>
<p>It saves you having to <code>const attributes = await permit.isOwner(resourceId) ? permit.ownAttributes : anyAttributes</code></p>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>resourceId</td>
<td>
<code>TResourceId</code>
</td>
<td>
Yes
</td>
<td>
<p>optional</p>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="../miscellaneous/typealiases.html#TAttributes" target="_self" >Promise<TAttributes></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="filterPick"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
filterPick
</b>
<a href="#filterPick"><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>filterPick(resourceItems: TSomeResourceItemWithId[])</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="362"
class="link-to-prism">src/Permit.class.ts:362</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<b>Type parameters :</b>
<ul class="type-parameters">
<li>TSomeResourceItemWithId</li>
</ul>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Given an array of <code>resourceItems</code>, it filters & maps to an array of <code>_.pick</code>-ed items, allowing only:</p>
<ul>
<li><p>the allowed items to pass through (eg only own, if only own possession is granted).</p>
</li>
<li><p>the allowed attributes in each item, based on ownership (if needed).</p>
</li>
</ul>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>resourceItems</td>
<td>
<code>TSomeResourceItemWithId[]</code>
</td>
<td>
No
</td>
<td>
<p>An array of <code>resourceItems</code> (eg an array of documents).
All resourceItems MUST have an 'id' property for the ownership check.</p>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code>Promise<Partial[]></code>
</div>
<div class="io-description">
<p>a filtered array of allowed items, each only with allowed attributes, i.e a <code>Promise<Partial<TSomeResourceItemWithId>[]></code>.</p>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="isListOwnSupported"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
isListOwnSupported
</b>
<a href="#isListOwnSupported"><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>isListOwnSupported()</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="224"
class="link-to-prism">src/Permit.class.ts:224</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<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>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="isOwn"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
isOwn
</b>
<a href="#isOwn"><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>isOwn(resourceId: TResourceId)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="159"
class="link-to-prism">src/Permit.class.ts:159</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Call <code>isOwn(resourceId)</code> to see if the granted User is the Owner of the particular <code>resourceId</code>.</p>
<p>Note the difference between <code>Permit::isOwn</code> and the PermissionDefinition <code>isOwner</code>:</p>
<p><code>Permit::isOwn</code> is composed from all the <code>isOwner</code> functions in PermissionsDefinitions that apply to this User.</p>
<p>It already has the <code>user</code> & <code>resource</code> baked in, so we only need to pass <code>resourceId</code>.</p>
<p>If any PermissionDefinitions <code>isOwner() === true</code> is found then it returns true, otherwise it returns <code>false</code>.</p>
<p><strong>Notes</strong></p>
<p> If the User has no "own" grant for the Action against the Resource, it still makes sense to call it:</p>
<p> Assume a <code>PermissionDefinition</code>:</p>
<div><pre class="line-numbers"><code class="language-js"> {
roles: ['EMPLOYEE'],
isOwner: async (resourceId) => [1,2,3].includes(resourceId),
grant: {
'read:any': ['id', 'title'],
'read:own': ['id', 'title', 'confidential'],
}
}</code></pre></div><p>and we request a <code>Permit</code> for <code>EMPLOYEE read document</code>, we should still be able to know which documents are OWN cause we might want to _.pick:</p>
<ul>
<li><p>ANY document with any <code>['id', 'title']</code></p>
</li>
<li><p>OWN documents with <code>['id', 'title', 'confidential']</code>, a permission we obtained from the <code>read:own</code> grant</p>
</li>
</ul>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>resourceId</td>
<td>
<code>TResourceId</code>
</td>
<td>
No
</td>
<td>
<p>The ID of the resource, eg <code>123</code></p>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code>Promise<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="limitOwn"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
limitOwn
</b>
<a href="#limitOwn"><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>limitOwn(context?: <a href="../undefineds/IContext.html">IContext<Tctx></a>)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="289"
class="link-to-prism">src/Permit.class.ts:289</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<b>Type parameters :</b>
<ul class="type-parameters">
<li>Tctx</li>
</ul>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Configures the actual <strong>query</strong> (or generates the <strong>filter</strong>) used to fetch the data from the data layer (eg the DB), using the conditions/restrictions imposed by the roles of the user, as these are defined in <code>limitOwned</code> ownership hooks in <code>PermissionDefinitions</code>.</p>
<p>The purpose of <code>limitOwn</code> is to allow the filtering of resources owned by the User <strong>lazily</strong> - in contrast with <code>listOwn()</code> which aggressively fetches all owned resourceIds of the User.</p>
<p>In other words, it configures (OR successively builds) a <strong>filter</strong> or <strong>query</strong>, but doesn't actually perform the filtering it self. Think of it as composing a function to pass to <code>Array.filter</code> or adding some <code>orWhere</code> clauses to an ORM query, but not actually executing the query.</p>
<p>It is agnostic of the ORM/DB engine used. This can work by passing an arbitrary <code>context</code> value (can be an Object, Array or any other accumulator of your choice) that holds the successive clauses, predicates etc of the owned restrictions defined as <code>limitOwned</code> hooks. For example the <code>context</code> in TypeORM could be a the <code>query</code> or a <code>subquery</code> object, before it has been executed.</p>
<p><strong>Note</strong>: the difference between <code>Permit::limitOwn</code> and <code>PermissionDefinition::limitOwned</code>: The <code>Permit::limitOwn</code> is a dynamically composed function of the potentially different <code>PermissionDefinition::limitOwned</code> functions attached to different <code>PermissionsDefinitions</code> that apply to this User (based on the roles user carries).</p>
<p>By default, to reduce all <code>PermissionDefinition::limitOwned</code> together, it calls all unique <code>limitOwned</code> functions found for the user, passing the <code>user</code> and the <code>context</code> value at each call and retrieving <code>context</code> back as the accumulator of that call. Finally it returns the resulting <code>context</code> value, whatever that might be. You can change this behavior, by using your own <code>limitOwnReduce</code>, passed at the Permissions constructor.</p>
<p><strong>Considerations</strong></p>
<ul>
<li><p>You must construct your <code>limitOwned</code> functions in the <code>PermissionsDefinitions</code>, using <strong>OR logic</strong> of the WHERE clauses or predicates, instead of an <strong>AND logic</strong>.</p>
<p> This is because for example a User that has both <code>EMPLOYEE</code> and <code>EMPLOYEE_MANAGER</code> roles, the resulting query should include all <code>EMPLOYEE_MANAGER</code> plus the <code>EMPLOYEE</code> filtered items (i.e their <strong>union</strong>).</p>
<p> If our subquery was build with <strong>AND logic</strong>, then only the items that satisfy both constraints would be filtered (ie. their <strong>intersection</strong>).</p>
</li>
<li><p>You must accumulate the existing <code>context</code> value(s), in the <code>context</code> value than you return from each <code>limitOwned</code> hook and then perhaps compose the final one from the <code>context</code> returned from the <code>limitOwn</code> call.</p>
</li>
</ul>
<p>Depending on the context you choose, you may provide <strong>your own</strong> <code>limitOwn()</code> version by passing a <code>limitOwnReduce</code> in the <code>Permissions</code> constructor - see below.</p>
<p>A TypeORM <code>query</code> object is the ideal context & use case for the default reduce logic of <code>limitOwn</code>. The <code>query</code> accumulates all calls to <code>andWhere</code> etc in its own self. Assuming a TypeORM app, with <code>PermissionDefinitions</code> like</p>
<div><pre class="line-numbers"><code class="language-js"> [
{
...
roles: 'RoleA'
limitOwned: (user, query) => query.orWhere(`"someField" = '${user.someField}'`);
},
{
...
roles: 'RoleB'
limitOwned: (user, query) => query.orWhere(`"otherField" = '${user.otherField}'`);
}
]</code></pre></div><p>you can simply do something like this in you app's code:</p>
<div><pre class="line-numbers"><code class="language-js"> query.andWhere(new Brackets(qb => permit.limitOwn(qb)));</code></pre></div><p>hence for a User with both RoleA & RoleB the resulting query will be augmented with a WHERE clause like</p>
<div><pre class="line-numbers"><code class="language-sql"> SELECT ...fields... FROM resource
WHERE ...existing where clauses....
AND ("someField" = 'someValue' OR "otherField" = 'otherValue') -- <<< the WHERE clause augmented by limitOwn()</code></pre></div><p>But if you were returning a function predicate, make sure your return something that accumulates the existing ones in the <code>context</code> and in the final call you take all into account.</p>
<p>There are many ways to achieve this, like functional composition or a simple collection, with or without context and with or without using <code>limitOwnReduce</code>.</p>
<p>See <a href="/additional-documentation/detailed-usage-&-examples.html">Example 5 with lodash & context and Example 6 for an even simpler one</a>.</p>
</div>
<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>context</td>
<td>
<code><a href="../miscellaneous/typealiases.html#IContext" target="_self" >IContext<Tctx></a></code>
</td>
<td>
Yes
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="https://www.typescriptlang.org/docs/handbook/basic-types.html" target="_blank" >any</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="listOwn"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
listOwn
</b>
<a href="#listOwn"><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>listOwn()</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="204"
class="link-to-prism">src/Permit.class.ts:204</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Returns an array of the <code>resourceIds</code> owned by the User, that can be used to filter the resource items the User can act on.</p>
<p><strong>How to Use</strong></p>
<p>In your app, you can do something like:</p>
<div><pre class="line-numbers"><code class="language-typescript"> const ownedDocumentIds = await permit.listOwn();
const query = `SELECT FROM document WHERE document.id in (${ownedDocumentIds.join(',')})`; // but if using Postgres/TypeORM be careful of issues like https://github.com/typeorm/typeorm/issues/2195#issuecomment-492991247)</code></pre></div><p>Note: the difference between <code>Permit::listOwn</code> and <code>PermissionDefinition::listOwned</code>:</p>
<p> <code>Permit::listOwn</code> is a dynamically composed function of the potentially different <code>isOwner</code> functions attached to different <code>PermissionsDefinitions</code> that apply to this User.</p>
<p>The composed function calls all the <code>listOwned</code> found for the user & <strong>returns the UNION of all resourceIds</strong>.</p>
<p><strong>Notes</strong></p>
<p>a) When <code>anyGranted = true</code></p>
<p>If <code>anyGranted</code> is true we usually expect the app to NOT filter the resources, since our User can access all documents. It is the responsibility of the userland's app, to check for <code>permit.anyGranted === true</code> and to avoid applying filtering on the DB query etc.</p>
<p>BUT <code>listOwn()</code> might still make sense, in case we want to handle differently user's own documents. In this case, if no <code>listOwned</code> is defined, it returns an empty [].</p>
<p>b) The <code>listOwn()</code> callback that returns a list of own ids is not scalable, if we potentially have too many (eg hundred thousand or millions) of owned resourceIds for a user and it could break the service (i.make it too slow).</p>
<p>The reason is that the callback is required to prefetch ALL ids of the resource owned by that user (in memory) and then probably use them to build an "IN (...ownedIds)" type query. And usually the service will go ahead and fetch only a small subset of those (eg a page of 10 or 50 resources).</p>
<p>For these reasons, you should use the <code>limitOwn()</code> hook - see below. Also in the near future, this hook will probably be DEPRECATED.</p>
</div>
<div class="io-description">
<b>Returns : </b> <code>Promise<TResourceId[]></code>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="mapPick"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
mapPick
</b>
<a href="#mapPick"><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>mapPick(resourceItems: TSomeResourceItemWithId[], projectTo: (item: TSomeResourceItemWithId) => void)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="388"
class="link-to-prism">src/Permit.class.ts:388</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<b>Type parameters :</b>
<ul class="type-parameters">
<li>TSomeResourceItemWithId</li>
</ul>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Given an array of <code>resourceItems</code> with an <code>id</code> property (eg an array of Document objects), it maps to a new Array where:</p>
<ul>
<li><p>first each item becomes a <code>projectedItem</code> (i.e mapped through <code>projectTo</code>).</p>
</li>
<li><p>then each <code>projectedItem</code> is <code>Permit.pick</code>-ed , allowing only the allowed attributes in each item, based on ownership of each item.</p>
</li>
</ul>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Default value</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>resourceItems</td>
<td>
<code>TSomeResourceItemWithId[]</code>
</td>
<td>
No
</td>
<td>
</td>
<td>
<p>An array of <code>resourceItems</code>.
Each needs to have an 'id' property for the ownership check.</p>
</td>
</tr>
<tr>
<td>projectTo</td>
<td>
<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/function" target="_blank" >function</a></code>
</td>
<td>
No
</td>
<td>
<code>_.identity</code>
</td>
<td>
<p>A sync or async function <code>(item:T) => any</code> projecting an item to any (like <code>Array.map)</code></p>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code>Promise<Partial[]></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="pick"></a>
<span class="name">
<b>
<span class="modifier">Public</span>
<span class="modifier">Async</span>
pick
</b>
<a href="#pick"><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>pick(resourceItem: TSomeResourceItemWithOptionalId, resourceIdOrOwn: TResourceId | boolean)</code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="337"
class="link-to-prism">src/Permit.class.ts:337</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<b>Type parameters :</b>
<ul class="type-parameters">
<li>TSomeResourceItemWithOptionalId</li>
</ul>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Helper to perform a <code>_.pick</code>-like operation of the allowed attributes from an object, based on <code>permit.attributes()</code>.</p>
<p>It checks for <code>isOwn</code> on the resource appropriately and picks attributes based on attributes defined on <code>own</code> or <code>any</code> permissions.
If user has no access to this resource at all, it returns an empty object.</p>
</div>
<div class="io-description">
<b>Parameters :</b>
<table class="params">
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Optional</td>
<td>Default value</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>resourceItem</td>
<td>
<code>TSomeResourceItemWithOptionalId</code>
</td>
<td>
No
</td>
<td>
</td>
<td>
<p>an object possibly with an <code>id</code> attribute to be used as the resourceId and check for ownership.</p>
</td>
</tr>
<tr>
<td>resourceIdOrOwn</td>
<td>
<code>TResourceId | boolean</code>
</td>
<td>
No
</td>
<td>
<code>resourceItem.id</code>
</td>
<td>
<p>optional, 2 uses:</p>
<ul>
<li>if a <code>Tid</code> is passed it ignores <code>resourceItem.id</code> and uses <code>resourceId</code> for the internal <code>isOwn()</code> check.</li>
<li>If <code>true</code> or <code>false</code> is passed, it overrides check and picks "own" or "any" attributes respectively.</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
<div>
</div>
<div class="io-description">
<b>Returns : </b> <code>Promise<Partial<TSomeResourceItemWithOptionalId>></code>
</div>
<div class="io-description">
</div>
</td>
</tr>
</tbody>
</table>
</section>
<section>
<h3 id="accessors">
Accessors
</h3>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="anyGranted"></a>
<span class="name"><b>anyGranted</b><a href="#anyGranted"><span class="icon ion-ios-link"></span></a></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="accessor"><b>get</b><code>anyGranted()</code></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="63" class="link-to-prism">src/Permit.class.ts:63</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Whether user is granted access to ANY resource.</p>
</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>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="ownGranted"></a>
<span class="name"><b>ownGranted</b><a href="#ownGranted"><span class="icon ion-ios-link"></span></a></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="accessor"><b>get</b><code>ownGranted()</code></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="71" class="link-to-prism">src/Permit.class.ts:71</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Whether user is granted access to a) OWN resources in general OR b) the particular <code>resourceId</code> (if provided).
Note that if <code>anyGranted === true</code>, then <code>ownGranted</code> will also be <code>true</code>.</p>
</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>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="anyAttributes"></a>
<span class="name"><b>anyAttributes</b><a href="#anyAttributes"><span class="icon ion-ios-link"></span></a></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="accessor"><b>get</b><code>anyAttributes()</code></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="82" class="link-to-prism">src/Permit.class.ts:82</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>The list of attributes the User can access on ANY resource.</p>
<p>Note: its more convenient to use <code>.attributes()</code></p>
<p>If the user has NO 'any' access (hence only OWN), it will be [] to signify that no 'any' access was granted.</p>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="../miscellaneous/typealiases.html#TAttributes" target="_self" >TAttributes</a></code>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="ownAttributes"></a>
<span class="name"><b>ownAttributes</b><a href="#ownAttributes"><span class="icon ion-ios-link"></span></a></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="accessor"><b>get</b><code>ownAttributes()</code></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="98" class="link-to-prism">src/Permit.class.ts:98</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>The list of attributes the User can access on OWN resources.
Note: its more convenient to use <code>.attributes()</code></p>
<br>
<p>If the user has NO 'own' access:</p>
<p> if they have 'any' access, then <code>ownAttributes</code> will be equal to <code>anyAttributes</code>, since there is no specific <code>own</code> access defined</p>
<p> if they dont have 'any' access, then it will be [].</p>
</div>
<div class="io-description">
<b>Returns : </b> <code><a href="../miscellaneous/typealiases.html#TAttributes" target="_self" >TAttributes</a></code>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="granted"></a>
<span class="name"><b>granted</b><a href="#granted"><span class="icon ion-ios-link"></span></a></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<span class="accessor"><b>get</b><code>granted()</code></span>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="112" class="link-to-prism">src/Permit.class.ts:112</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>The calculated property <code>granted</code> is a shortcut helper that grants access:</p>
<p>a) if either <code>anyGranted</code> or <code>ownGranted</code> is true, when <code>resourceId</code> is NOT KNOWN at <code>grantPermit()</code> query time.
Note that its up to the library user to check <code>anyGranted</code> before granting access to a any specific <code>resourceId</code> later on, or to ask <code>isOwn(resourceId)</code> otherwise.</p>
<p>b) if ONLY <code>ownGranted</code> is true, but <code>resourceId</code> is known and actually owned by the user. The <code>grantPermit()</code> call has already calculated the correct value of <code>ownGranted</code> if <co