UNPKG

@superawesome/permissions

Version:

Fine grained permissions / access control with ownerships & attribute picking, done right.

1,081 lines (940 loc) 74.9 kB
<!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> &amp; 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 &amp; further querying you might require for your current request, you&#39;ll find it here.</p> <p><strong>Note</strong>: <code>Permit</code> constructor is private, you shouldn&#39;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> &amp; <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&#39;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&lt;TAttributes&gt;</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 &amp; 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 &#39;id&#39; property for the ownership check.</p> </td> </tr> </tbody> </table> </div> <div> </div> <div class="io-description"> <b>Returns : </b> <code>Promise&lt;Partial[]&gt;</code> </div> <div class="io-description"> <p>a filtered array of allowed items, each only with allowed attributes, i.e a <code>Promise&lt;Partial&lt;TSomeResourceItemWithId&gt;[]&gt;</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> &amp; <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 &quot;own&quot; 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: [&#39;EMPLOYEE&#39;], isOwner: async (resourceId) =&gt; [1,2,3].includes(resourceId), grant: { &#39;read:any&#39;: [&#39;id&#39;, &#39;title&#39;], &#39;read:own&#39;: [&#39;id&#39;, &#39;title&#39;, &#39;confidential&#39;], } }</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>[&#39;id&#39;, &#39;title&#39;]</code></p> </li> <li><p>OWN documents with <code>[&#39;id&#39;, &#39;title&#39;, &#39;confidential&#39;]</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&lt;boolean&gt;</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&#39;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 &amp; 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: &#39;RoleA&#39; limitOwned: (user, query) =&gt; query.orWhere(`&quot;someField&quot; = &#39;${user.someField}&#39;`); }, { ... roles: &#39;RoleB&#39; limitOwned: (user, query) =&gt; query.orWhere(`&quot;otherField&quot; = &#39;${user.otherField}&#39;`); } ]</code></pre></div><p>you can simply do something like this in you app&#39;s code:</p> <div><pre class="line-numbers"><code class="language-js"> query.andWhere(new Brackets(qb =&gt; permit.limitOwn(qb)));</code></pre></div><p>hence for a User with both RoleA &amp; 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 (&quot;someField&quot; = &#39;someValue&#39; OR &quot;otherField&quot; = &#39;otherValue&#39;) -- &lt;&lt;&lt; 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-&amp;-examples.html">Example 5 with lodash &amp; 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&lt;Tctx&gt;</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(&#39;,&#39;)})`; // 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 &amp; <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&#39;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&#39;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 &quot;IN (...ownedIds)&quot; 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&lt;TResourceId[]&gt;</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 &#39;id&#39; 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) =&gt; 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&lt;Partial[]&gt;</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 &quot;own&quot; or &quot;any&quot; attributes respectively.</li> </ul> </td> </tr> </tbody> </table> </div> <div> </div> <div class="io-description"> <b>Returns : </b> <code>Promise&lt;Partial&lt;TSomeResourceItemWithOptionalId&gt;&gt;</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 &#39;any&#39; access (hence only OWN), it will be [] to signify that no &#39;any&#39; 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 &#39;own&#39; access:</p> <p> if they have &#39;any&#39; 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 &#39;any&#39; 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