{"_id":"@allams/resource-name-permissions","_rev":"3-062e6632a1bd56cc114a9a76a2a4f606","name":"@allams/resource-name-permissions","description":"Node.js library for Resource Name Permissions","dist-tags":{"latest":"3.0.3"},"versions":{"3.0.0":{"name":"@allams/resource-name-permissions","version":"3.0.0","author":{"name":"Steve Allam"},"license":"ISC","_id":"@allams/resource-name-permissions@3.0.0","maintainers":[{"name":"allams","email":"steve.allam@imhotek.com"}],"homepage":"https://github.com/steve-allam/resource-name-permissions#readme","bugs":{"url":"https://github.com/steve-allam/resource-name-permissions/issues"},"dist":{"shasum":"f2349dedfd5577d4f6c7d452a6ea9d51bdbfcc9c","tarball":"https://registry.npmjs.org/@allams/resource-name-permissions/-/resource-name-permissions-3.0.0.tgz","fileCount":16,"integrity":"sha512-Srz5dcN0jXqMgUjfKlMmAlVRh+PG+7YTDMea/AHYxG+0La9klneDSNBCiHyMcBdlQvHymX4ASHkDel9TgMKgHg==","signatures":[{"sig":"MEQCIGCsLhUQwtTZt3Bc7FdYX9mahDJQfobP1bk8sTErT+BrAiBMrCtl1PLzeTK376dX8jrQ6aAh2md1ulIMHnovFhMqNw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":57142},"main":"lib/index.js","type":"module","gitHead":"2aea8f5fc125ff98f7cccbb4f3697c9a1643f6a4","scripts":{"test":"mocha","cpsrc":"copyfiles src/*.js lib","publish":"npx eslint src/*.js && npm run cpsrc"},"_npmUser":{"name":"allams","email":"steve.allam@imhotek.com"},"repository":{"url":"git+https://github.com/steve-allam/resource-name-permissions.git","type":"git"},"_npmVersion":"8.5.5","description":"Node.js library for Resource Name Permissions","directories":{},"_nodeVersion":"18.16.0","dependencies":{"lodash":"^4.17.21"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^5.1.1","mocha":"^10.6.0","assert":"^2.1.0","eslint":"^9.6.0","globals":"^15.8.0","copyfiles":"^2.4.1","@eslint/js":"^9.6.0","@types/node":"^20.14.9","@types/mocha":"^10.0.7"},"_npmOperationalInternal":{"tmp":"tmp/resource-name-permissions_3.0.0_1720112496374_0.0012768631249149287","host":"s3://npm-registry-packages"}},"3.0.1":{"name":"@allams/resource-name-permissions","version":"3.0.1","author":{"name":"Steve Allam"},"license":"ISC","_id":"@allams/resource-name-permissions@3.0.1","maintainers":[{"name":"allams","email":"steve.allam@imhotek.com"}],"homepage":"https://github.com/steve-allam/resource-name-permissions#readme","bugs":{"url":"https://github.com/steve-allam/resource-name-permissions/issues"},"dist":{"shasum":"d507e586d98dcee5a5414df4e87c59683f4f02c7","tarball":"https://registry.npmjs.org/@allams/resource-name-permissions/-/resource-name-permissions-3.0.1.tgz","fileCount":10,"integrity":"sha512-BZICyTVBqxpLijzVPa5NCzlrCNWAmqQUCVDpBhFTHXEMWv9Ah4mZsF8z2QgBdFveSTw3eMo2EMaTrS+tAC412w==","signatures":[{"sig":"MEUCIQDn5Ijv28AMeELYaEKxkDpgRMIPSq+qzOoHzpBeJECkbgIgQ7efT6HQDOm4w7GVdCdM0nPFOJFu5hrLNMmv8WII92I=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":34074},"main":"lib/index.js","type":"module","gitHead":"2aea8f5fc125ff98f7cccbb4f3697c9a1643f6a4","scripts":{"test":"mocha","build":"npx eslint src/*.js && npm run cpsrc","cpsrc":"copyfiles -u 1 src/*.js lib","publish":"npm publish --access public"},"_npmUser":{"name":"allams","email":"steve.allam@imhotek.com"},"repository":{"url":"git+https://github.com/steve-allam/resource-name-permissions.git","type":"git"},"_npmVersion":"8.5.5","description":"Node.js library for Resource Name Permissions","directories":{},"_nodeVersion":"18.16.0","dependencies":{"lodash":"^4.17.21"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^5.1.1","mocha":"^10.6.0","assert":"^2.1.0","eslint":"^9.6.0","globals":"^15.8.0","copyfiles":"^2.4.1","@eslint/js":"^9.6.0","@types/node":"^20.14.9","@types/mocha":"^10.0.7"},"_npmOperationalInternal":{"tmp":"tmp/resource-name-permissions_3.0.1_1720113023703_0.2992517087272768","host":"s3://npm-registry-packages"}},"3.0.2":{"name":"@allams/resource-name-permissions","version":"3.0.2","author":{"name":"Steve Allam"},"license":"ISC","_id":"@allams/resource-name-permissions@3.0.2","maintainers":[{"name":"allams","email":"steve.allam@imhotek.com"}],"homepage":"https://github.com/steve-allam/resource-name-permissions#readme","bugs":{"url":"https://github.com/steve-allam/resource-name-permissions/issues"},"dist":{"shasum":"1e147191b01d77b5130b473ad7ca671f858bf06f","tarball":"https://registry.npmjs.org/@allams/resource-name-permissions/-/resource-name-permissions-3.0.2.tgz","fileCount":10,"integrity":"sha512-QimIHOHYi3UFLaPxgyhwb1odrlL+/ckL7Cf6pl5hOXNRFwrZwCgskFJxO2mC3SU2Emmsk+X0RuuYtXOCar7jZg==","signatures":[{"sig":"MEYCIQDgA1yQ7bX9lCT8Ld0wuNYhfxYfB4UBrnvIm4P0joDl3AIhANOultRaRjQaBzYQ0/z4StOz9Rt0TlXGN+mVab0j96wr","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":34074},"main":"lib/index.js","type":"module","gitHead":"d6abb07eadde5ff500c5b539d147ff67a3a4507e","scripts":{"test":"mocha","build":"npx eslint src/*.js && npm run cpsrc","cpsrc":"copyfiles -u 1 src/*.js lib","publish":"npm publish --access public"},"_npmUser":{"name":"allams","email":"steve.allam@imhotek.com"},"repository":{"url":"git+https://github.com/steve-allam/resource-name-permissions.git","type":"git"},"_npmVersion":"8.5.5","description":"Node.js library for Resource Name Permissions","directories":{},"_nodeVersion":"18.16.0","dependencies":{"lodash":"^4.17.21"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^5.1.1","mocha":"^10.6.0","assert":"^2.1.0","eslint":"^9.6.0","globals":"^15.8.0","copyfiles":"^2.4.1","@eslint/js":"^9.6.0","@types/node":"^20.14.9","@types/mocha":"^10.0.7"},"_npmOperationalInternal":{"tmp":"tmp/resource-name-permissions_3.0.2_1720113193787_0.6289768445571355","host":"s3://npm-registry-packages"}},"3.0.3":{"name":"@allams/resource-name-permissions","version":"3.0.3","description":"Node.js library for Resource Name Permissions","main":"lib/index.js","author":{"name":"Steve Allam"},"license":"ISC","type":"module","repository":{"type":"git","url":"git+https://github.com/steve-allam/resource-name-permissions.git"},"devDependencies":{"@eslint/js":"^9.6.0","@types/mocha":"^10.0.7","@types/node":"^20.14.9","assert":"^2.1.0","chai":"^5.1.1","copyfiles":"^2.4.1","eslint":"^9.6.0","globals":"^15.8.0","mocha":"^10.6.0"},"scripts":{"cpsrc":"copyfiles -u 1 src/*.js lib","test":"mocha","build":"npx eslint src/*.js && npm run cpsrc","publish":"npm publish --access public"},"dependencies":{"lodash":"^4.17.21"},"gitHead":"8d4d9239b72742c2f992eaa60186f5b62ba4899f","bugs":{"url":"https://github.com/steve-allam/resource-name-permissions/issues"},"homepage":"https://github.com/steve-allam/resource-name-permissions#readme","_id":"@allams/resource-name-permissions@3.0.3","_nodeVersion":"18.16.0","_npmVersion":"8.5.5","dist":{"integrity":"sha512-g9Gz9yn0biTGZtSWZ/8I0m3qr0J3Iil4t1N9XTJVE/I1n3+LQPKFVfnCOzza/482lMghma3IABJzogjmEnpgEA==","shasum":"3d33e58afc418828e8ecea4b4fe6cdbadd0d94b5","tarball":"https://registry.npmjs.org/@allams/resource-name-permissions/-/resource-name-permissions-3.0.3.tgz","fileCount":10,"unpackedSize":35502,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHVBDsHFxHtHJmdJ5e9X3epSTHckq0zPZIs9DfW4zbQ+AiAVFwUfcHLt75w1+YS0g9NMATTJRZUZHVTsuukL4Q9eVQ=="}]},"_npmUser":{"name":"allams","email":"steve.allam@imhotek.com"},"directories":{},"maintainers":[{"name":"allams","email":"steve.allam@imhotek.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/resource-name-permissions_3.0.3_1720114401739_0.9884498292300818"},"_hasShrinkwrap":false}},"time":{"created":"2024-07-04T17:01:36.246Z","modified":"2024-07-04T17:33:22.126Z","3.0.0":"2024-07-04T17:01:36.668Z","3.0.1":"2024-07-04T17:10:23.900Z","3.0.2":"2024-07-04T17:13:13.925Z","3.0.3":"2024-07-04T17:33:21.969Z"},"maintainers":[{"name":"allams","email":"steve.allam@imhotek.com"}],"author":{"name":"Steve Allam"},"repository":{"type":"git","url":"git+https://github.com/steve-allam/resource-name-permissions.git"},"license":"ISC","homepage":"https://github.com/steve-allam/resource-name-permissions#readme","bugs":{"url":"https://github.com/steve-allam/resource-name-permissions/issues"},"readme":"# Node.js Resource Name Permissions\r\n\r\nThis is a fork from the original resourse-name-permissions, which fixes a bug and adds a couple more functions.  The module is useful in cases where you have hierarchical resources which need permissions at one or more levels.\r\n\r\nThis Node.js library facilitates formatting permissions for users, groups or other security principals in the following format:\r\n\r\n```\r\n<identifier>?<privileges>\r\n```\r\n\r\n**Example:**\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\nif (!permission('us-east-1:article?read,create').allows('us-east-1:article?read')) {\r\n  throw new Error('Not allowed here!');\r\n}\r\n```\r\n\r\n# Description\r\n\r\nResource Name Permissions are a flexible method to express privileges in a succinct way.\r\n\r\nThey are inspired by [Github's OAauth Scopes](https://developer.github.com/changes/2014-02-24-finer-grained-scopes-for-ssh-keys/) and [Amazon's Resource Names](http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html).\r\n\r\n## Format\r\n\r\n```\r\n<identifier>?<privileges>\r\n```\r\n\r\nA Resource Name Permission consists of two components, an identifier and privilege(s).\r\n\r\n1. **Identifier**\r\n\r\n    The identifier specifies which entitie(s) the permission applies to. Valid characters are `a-Z`, `0-9`, `-`, `_`, `.` and `+`. Special characters are `/`, `:` and `*`.\r\n\r\n    Both `/` and `:` serve the same purpose and enable you to hierarchically organize identifier names. Organizing identifiers is particularly useful in combination with wildcards. Whether you use `/` and/or `:` is entirely up to you.\r\n\r\n    The `*` wildcard matches any (or zero) characters excluding `/` and `:`, whereas `**` matches any (or zero) characters including `/` and `:`. The `**` is only valid when preceded and followed by a `/`, `:` or at the start/end of the identifier string. A single wildcard `*` can be used anywhere within an identifier string.\r\n\r\n    For example, to read a user comment with identifier `article/1234/comments/54` one of the following would grant access:\r\n\r\n    ```\r\n    article/1234/comments/54?read\r\n    article/1234/comments/54?admin\r\n    article/*/comment/*?read\r\n    article/*/*/*?read\r\n    article/**?read\r\n    **?read\r\n    ```\r\n\r\n    These will NOT grant access:\r\n\r\n    ```\r\n    article:1234:comments:54?read\r\n    article/1234/comments/54?update\r\n    article/*?read\r\n    ```\r\n\r\n2. **Privileges**\r\n\r\n    Privileges specify which operations are allowed on a resource. You can either specify these as a comma-separated set of names, a bitmask, or a combination thereof. For example, `create,read,update,delete`, `15` and `crud` are all equivalent. Privileges are fully customizable.\r\n\r\n    The privileges configured by default are:\r\n\r\n    Bitmask | Name            | Description\r\n    --------|-----------------|-----------------\r\n    `1`     | `read`          | View resource.\r\n    `2`     | `create`        | Create resource.\r\n    `4`     | `update`        | Update resource.\r\n    `8`     | `delete`        | Delete resource.\r\n    `15`    | `crud`          | All of the above.\r\n    `16`    | `manage`        | Set permissions of subject without `manage` or `super` privilege.\r\n    `31`    | `manager`       | All of the above.\r\n    `32`    | `own`           | Set permissions of subjects without `super` privilege + allow ownership transfer.\r\n    `63`    | `owner`         | All of the above.\r\n    `64`    | `admin`         | Enables special administrative actions and setting permissions of everyone.\r\n    `127`   | `administrator` | All of the above.\r\n\r\n# permission(perm)\r\n\r\nThe `permission(perm)` function enables a variety of evaluation and transformation methods. To evaluate a collection of permissions scroll down until you hit the `permissions(perms[])` section.\r\n\r\n## allows(...searchPermissions[])\r\n\r\nReturns `true` if all `searchPermissions` are matched by the permission, otherwise returns `false`.\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\n// Basic examples\r\npermission('article?read').allows('article?read'); // true\r\npermission('project-1:article?read').allows('project-1:article?read'); // true\r\npermission('project-1:article?read').allows('article?read'); // false\r\npermission('article?read,update').allows('article?read'); // true\r\npermission('article?crud').allows('article?read,update'); // false\r\npermission('article?read,update').allows('article?crud'); // false\r\n\r\n// Multiple permissions\r\npermission('article?read,update').allows('article?read', 'article?update'); // true\r\npermission('article?read,update').allows(['article?read', 'article?update']); // true\r\npermission('article?read').allows('article?read', 'article?update'); // false\r\npermission('article?read').allows('article?read', 'article?update'); // false\r\n\r\n// Wildcards * and **\r\npermission('art*?read').allows('article?read'); // true\r\npermission('article/*?read').allows('article/1234?read'); // true\r\npermission('article/1234?read').allows('article/*?read'); // false\r\npermission('article/*?read').allows('article?read'); // false\r\npermission('article/*?read').allows('article/1234/comment?read'); // false\r\npermission('article/**?read').allows('article/1234/comment?read'); // true\r\npermission('article/**?read').allows('article/1234:comment?read'); // true\r\n```\r\n\r\n## identifier([ identifier ])\r\n\r\nGets or sets the permission identifier.\r\n\r\n```js\r\nconst perm = permission('article/1234/comment/21?read');\r\n\r\nperm.identifier(); // \"article/1234/comment/21\"\r\nperm.path('article/998');\r\nperm.path(); // \"article/998\"\r\n```\r\n\r\n## privileges([ privileges ])\r\n\r\nSets or returns priviliges.\r\n\r\n`privileges` can be either an array or comma-separated string with privilege names or their bitmasks. For example, `13`, `read`, `owner`, and `read,update,3` are valid.\r\n\r\nWhen `privileges` are not defined it returns a bitmask of all privileges.\r\n\r\n```js\r\nconst perm = permission('article/1234?read');\r\n\r\nperm.privileges(); // 1\r\nperm.privileges('crud,own');\r\nperm.privileges(); // 15 | 32 = 47\r\nperm.privileges(['crud', 'manage', 'owner']);\r\nperm.privileges(); // 15 | 16 | 63 = 63\r\n```\r\n\r\n## hasPrivilege(privilege)\r\n\r\nReturn `true` when permission has specified privilege(s).\r\n\r\n`privileges` can be either an array or comma-separated string with privilege names or their bitmasks.\r\n\r\n```js\r\nconst perm = permission('article/1234?crud');\r\n\r\nperm.hasPrivilege('read'); // true\r\nperm.hasPrivilege(['read', 'create', 'update']); // true\r\nperm.hasPrivilege('crud'); // true\r\nperm.hasPrivilege('crud,read,create'); // true\r\nperm.hasPrivilege('admin'); // false\r\nperm.hasPrivilege('unknown'); // throws error\r\n```\r\n\r\n## hasPrivileges()\r\n\r\nAlias of `hasPrivilege()`.\r\n\r\n## grantPrivileges()\r\n\r\nGets array with privilege names that enable granting privileges.\r\n\r\nReturns empty array when none of permission's privileges are grant privileges.\r\n\r\n```js\r\nconst perm = permission('article/1234?read,manage,64');\r\n\r\nperm.grantPrivileges(); // ['manage', 'admin']\r\n```\r\n\r\n## mayGrant(newPermission [, granteePermissions])\r\n\r\nReturns `true` if permission allows granting `newPermission` to grantee.\r\n\r\nIn the grant process we distinguish two roles:\r\n\r\n- *grantor*: the person granting or revoking a permission.\r\n- *grantee*: the person receiving or losing a permission.\r\n\r\nTo grant a permission the grantor must have **manage** an/or **super** privilege.\r\n\r\n- **manage** allows granting or revoking **crud** privileges from anyone without **manage** and **super** privilege.\r\n- **super** allows granting and revoking permissions from anyone.\r\n\r\nThe grantor/grantee privileges can be customized using `permission.config()`.\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\npermission('article?manage').mayGrant('article?read', []); // true\r\npermission('article?manage').mayGrant('article?read', ['article?delete']); // true\r\npermission('article?manage').mayGrant('article?read', ['article?admin']); // true\r\npermission('article?manage').mayGrant('article?manage', ['article?manage']); // false\r\npermission('article?manage').mayGrant('article?read', ['unrelated?admin']); // true\r\n\r\npermission('article?admin').mayGrant('article/1234?read', ['article?manage']); // true\r\npermission('article?admin').mayGrant('article/1234?read', ['article?admin']); // true\r\n```\r\n\r\n## mayRevoke(permission [, granteePermissions])\r\n\r\nReturns `true` if permission allows revoking `permission` to grantee.\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\npermission('article?manage').mayRevoke('article?read', []); // true\r\npermission('article?manage').mayRevoke('article?read', ['article?admin']); // false\r\npermission('article?manage').mayRevoke('article?manage', ['article?manage']); // false\r\n\r\npermission('article?admin').mayRevoke('article/1234?read', ['article?manage']); // true\r\npermission('article?admin').mayRevoke('article/1234?read', ['article?admin']); // true\r\n```\r\n\r\n## toObject()\r\n\r\nReturns an object representation of a resource name permission containing `identifier` and `privileges`.\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\npermission('article/*?crud').toObject();\r\n// {\r\n//   identifier: 'article/*',\r\n//   privileges: 15,\r\n// }\r\n```\r\n\r\n## toString()\r\n\r\nReturns a string representation of a resource name permission. Privileges are always represented by their bitmask.\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\npermission('article/*?crud').toString();\r\n// 'article/*:15'\r\n```\r\n\r\n## clone()\r\n\r\nReturns a clone of the permission.\r\n\r\n```js\r\nconst a = permission('article?read');\r\nconst b = a.clone();\r\n```\r\n\r\nAlternatively you can do this:\r\n\r\n```js\r\nconst a = permission('article?read');\r\nconst b = permission(a);\r\n```\r\n\r\n## validate()\r\n\r\nStatic method to check if permission string is valid.\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\npermission.validate('article:unknown'); // false, unknown privilege\r\npermission.validate('article:**?read'); // true\r\npermission.validate('article:test**?read'); // false\r\npermission.validate('article:test*?read'); // true\r\n```\r\n\r\n## config(options)\r\n\r\nStatic method to change global config options. Changing global config doesn't affect existing instances.\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\npermission.config({\r\n  privileges: {\r\n    read: 1,\r\n    create: 2,\r\n    update: 4,\r\n    delete: 8,\r\n    crud: 15,\r\n    manage: 16,\r\n    manager: 31,\r\n    own: 32,\r\n    owner: 63,\r\n    admin: 64,\r\n    administrator: 127,\r\n  },\r\n  grantPrivileges: {\r\n    manage: 16,\r\n    own: 32,\r\n    admin: 64,\r\n  },\r\n});\r\n```\r\n\r\n### Grant privileges\r\n\r\nThe config option `grantPrivileges` must be an object of key-value pairs where each key is a privilege name and each value a bitmask specifying which privileges it is allowed to grant.\r\n\r\nAnyone with grant privileges is allowed to grant its privileges to grantees without any grant privileges. However, if a grantee does have grant privileges its grant privileges must be covered by those of the grantor.\r\n\r\nExample:\r\n\r\n```js\r\nimport { permission } from 'resource-name-permissions';\r\n\r\npermission.config({\r\n  privileges: {\r\n    a: 1,\r\n    x: 2,\r\n    y: 4,\r\n    z: 8,\r\n  },\r\n  grantPrivileges: {\r\n    x: 1,\r\n    y: 3, // 1 | 2 => a and x are allowed\r\n    z: 9, // 1 | 8 => a and z are allowed\r\n  },\r\n});\r\n\r\npermission('article?x').mayGrant('article?a'); // true\r\npermission('article?x').mayGrant('article?a', ['article?x']); // false\r\npermission('article?y').mayGrant('article?a', ['article?x']); // true\r\npermission('article?y').mayGrant('article?x', ['article?x']); // true\r\npermission('article?y').mayGrant('article?a', ['article?y']); // false\r\npermission('article?z').mayGrant('article?a', ['article?z']); // true\r\n```\r\n\r\nNotice the last example where `z` may grant a permission to a grantee with `z`, whereas an `y` may not grant the same permission to another `y`. We'll leave it to you to figure out why.\r\n\r\n# permissions(perms)\r\n\r\nThe `permissions(perms)` function enables verifying a collection of permissions.\r\n\r\nValid `perms` are permission strings, `permission()` objects, or arrays of either of those.\r\n\r\n## allows(searchPermissions[])\r\n\r\nReturns `true` if all `searchPermissions` are matched by any single or a combination of `permissions`.\r\n\r\nThis method intelligently handles privileges.\r\n\r\n```js\r\nimport { permissions } from 'resource-name-permissions';\r\n\r\npermissions('article?read', 'article?update').allows('article?ru'); // true\r\npermissions('article/*?read', 'article/*?update').allows('article/1234?ru'); // true\r\n```\r\n\r\n## allowsBy(searchPermissions[]) \\*\\*new\\*\\*\r\n\r\nReturns an array containing all of the permissions that would allow the `searchpermissions`. An empty array is returned if none would match.\r\n\r\nThis method intelligently handles privileges.\r\n\r\n```js\r\nimport { permissions } from 'resource-name-permissions';\r\n\r\npermissions('article?read', 'article?update').allowsBy('article?read'); // ['article?read', 'article?update']\r\npermissions('article/*?read', 'article/*?update').allowsBy('article/1234?update'); // ['article/*?update']\r\n```\r\n\r\n## hasChildren(identifier)  \\*\\*new\\*\\*\r\n\r\nReturns `true` if there are permissions that can be called 'children' of the `identifier`.\r\nThis method can be used to manage permissions, perhaps in an interface that works down a known hierarchy to only show those objects that a user has any permissions to.\r\n\r\n\r\n```js\r\nimport { permissions } from 'resource-name-permissions';\r\n\r\nvar perms = []'server/appserver1/database/users?read', 'server/appserver2/database/x?update']\r\npermissions(perms).hasChildren('server'); // true\r\npermissions(perms).hasChildren('server/appserver2/database'); // true\r\npermissions(perms).hasChildren('server/appserver3'); // false\r\n\r\n```\r\n\r\n## mayGrant(newPermission [, granteePermissions])\r\n\r\nReturns `true` if any or a combination of this collection's permissions allow granting `newPermission` to grantee.\r\n\r\nFor a better understanding of how granting work, see `permission().mayGrant(...)`.\r\n\r\n```js\r\nimport { permissions } from 'resource-name-permissions';\r\n\r\npermission('article?read', 'article?m').mayGrant('article?read'); // true\r\n```\r\n\r\n## mayRevoke(removePermission [, granteePermissions])\r\n\r\nAn alias of `permissions().mayGrant()`.\r\n\r\nReturns `true` if any or a combination of this collection's permissions allow revoking `removePermission` from grantee.\r\n\r\n## permissions([ permissions ])\r\n\r\nGets or sets permissions.\r\n\r\n`permissions` can be either a string or an array of permissions.\r\n","readmeFilename":"README.md"}