2023-03-23 00:36:30 +01:00

21 lines
16 KiB
JSON

{
"title": "@chronark/access",
"description": "A minimal library for access control. It is designed to be used together with opaque access tokens by providing a simple interface to define roles with different access permissions and verifying requests to resources.",
"date": "2022-11-13T00:00:00.000Z",
"repository": "chronark/access",
"body": {
"raw": "A minimal library for access control. It is designed to be used together with opaque access tokens by providing a simple interface to define roles with different access permissions and verifying requests to resources.\n\n- Fully typed\n- Zero dependencies\n- Serializable to store in a database\n\n## Install\n\n```sh-session\nnpm i @chronark/access\n```\n\n## Usage\n\n```ts\nimport { AccessControl, Role } from \"@chronark/access\";\n\n/**\n * Define all your resources and their access patterns\n *\n * key => resource\n * value => array of access types\n */\ntype Statements = {\n user: [\"read\", \"write\", \"dance\"];\n team: [\"read\", \"write\"];\n};\n\n/**\n * Create an access control instance and pass the Statements type to enjoy full\n * type safety\n */\nconst ac = new AccessControl<Statements>();\n\n/**\n * Now you can define one or more roles by specifying the access permissions\n *\n * This is already fully typed and typescript will let you know if you try to\n * use anything, that is not defined in the Statements type.\n */\nconst role = ac.newRole({\n user: [\"read\", \"write\"],\n team: [\"read\"],\n});\n\n/**\n * Simulate storing and retrieving the role in a database\n *\n * The idea here is, that you can store permissions alongside an API token.\n * Now, when you verify the token, you can also verify the access permissions.\n */\nconst serialized = role.toString();\n\n/**\n * Note how you can pass in the Statements type again, to get full type safety\n */\nconst recovered = Role.fromString<Statements>(serialized);\n\n/**\n * Validate the role by specifying the resource and the required access\n *\n * everything is fully typed\n */\nconst res = recovered.authorize({\"team\", [\"read\"]});\n\n// res.success => boolean\n// res.error => string | undefined provides a reason for failure\n```",
"code": "var Component=(()=>{var h=Object.create;var a=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var E=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty;var F=(l,e)=>()=>(e||l((e={exports:{}}).exports,e),e.exports),N=(l,e)=>{for(var s in e)a(l,s,{get:e[s],enumerable:!0})},o=(l,e,s,r)=>{if(e&&typeof e==\"object\"||typeof e==\"function\")for(let c of y(e))!m.call(l,c)&&c!==s&&a(l,c,{get:()=>e[c],enumerable:!(r=p(e,c))||r.enumerable});return l};var u=(l,e,s)=>(s=l!=null?h(E(l)):{},o(e||!l||!l.__esModule?a(s,\"default\",{value:l,enumerable:!0}):s,l)),f=l=>o(a({},\"__esModule\",{value:!0}),l);var t=F((v,i)=>{i.exports=_jsx_runtime});var B={};N(B,{default:()=>D,frontmatter:()=>g});var n=u(t()),g={title:\"@chronark/access\",description:\"A minimal library for access control. It is designed to be used together with opaque access tokens by providing a simple interface to define roles with different access permissions and verifying requests to resources.\",repository:\"chronark/access\",date:\"2022-11-13\"};function d(l){let e=Object.assign({p:\"p\",ul:\"ul\",li:\"li\",h2:\"h2\",a:\"a\",span:\"span\",div:\"div\",pre:\"pre\",code:\"code\"},l.components);return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.p,{children:\"A minimal library for access control. It is designed to be used together with opaque access tokens by providing a simple interface to define roles with different access permissions and verifying requests to resources.\"}),`\n`,(0,n.jsxs)(e.ul,{children:[`\n`,(0,n.jsx)(e.li,{children:\"Fully typed\"}),`\n`,(0,n.jsx)(e.li,{children:\"Zero dependencies\"}),`\n`,(0,n.jsx)(e.li,{children:\"Serializable to store in a database\"}),`\n`]}),`\n`,(0,n.jsxs)(e.h2,{id:\"install\",children:[(0,n.jsx)(e.a,{className:\"subheading-anchor\",\"aria-label\":\"Link to section\",href:\"#install\",children:(0,n.jsx)(e.span,{className:\"icon icon-link\"})}),\"Install\"]}),`\n`,(0,n.jsx)(e.div,{\"data-rehype-pretty-code-fragment\":\"\",children:(0,n.jsx)(e.pre,{\"data-language\":\"sh-session\",\"data-theme\":\"default\",children:(0,n.jsx)(e.code,{\"data-language\":\"sh-session\",\"data-theme\":\"default\",children:(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#e1e4e8\"},children:\"npm i @chronark/access\"})})})})}),`\n`,(0,n.jsxs)(e.h2,{id:\"usage\",children:[(0,n.jsx)(e.a,{className:\"subheading-anchor\",\"aria-label\":\"Link to section\",href:\"#usage\",children:(0,n.jsx)(e.span,{className:\"icon icon-link\"})}),\"Usage\"]}),`\n`,(0,n.jsx)(e.div,{\"data-rehype-pretty-code-fragment\":\"\",children:(0,n.jsx)(e.pre,{\"data-language\":\"ts\",\"data-theme\":\"default\",children:(0,n.jsxs)(e.code,{\"data-language\":\"ts\",\"data-theme\":\"default\",children:[(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"import\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" { AccessControl, Role } \"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"from\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"@chronark/access\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\";\"})]}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:\" \"}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\"/**\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * Define all your resources and their access patterns\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" *\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * key => resource\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * value => array of access types\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" */\"})}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"type\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#B392F0\"},children:\"Statements\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"=\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" {\"})]}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#FFAB70\"},children:\"user\"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\":\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" [\"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"read\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\", \"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"write\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\", \"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"dance\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"];\"})]}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#FFAB70\"},children:\"team\"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\":\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" [\"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"read\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\", \"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"write\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"];\"})]}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"};\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:\" \"}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\"/**\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * Create an access control instance and pass the Statements type to enjoy full\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * type safety\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" */\"})}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"const\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#79B8FF\"},children:\"ac\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"=\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"new\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#B392F0\"},children:\"AccessControl\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"<\"}),(0,n.jsx)(e.span,{style:{color:\"#B392F0\"},children:\"Statements\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\">();\"})]}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:\" \"}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\"/**\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * Now you can define one or more roles by specifying the access permissions\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" *\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * This is already fully typed and typescript will let you know if you try to\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * use anything, that is not defined in the Statements type.\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" */\"})}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"const\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#79B8FF\"},children:\"role\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"=\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" ac.\"}),(0,n.jsx)(e.span,{style:{color:\"#B392F0\"},children:\"newRole\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"({\"})]}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" user: [\"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"read\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\", \"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"write\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"],\"})]}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" team: [\"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"read\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"],\"})]}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"});\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:\" \"}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\"/**\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * Simulate storing and retrieving the role in a database\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" *\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * The idea here is, that you can store permissions alongside an API token.\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * Now, when you verify the token, you can also verify the access permissions.\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" */\"})}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"const\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#79B8FF\"},children:\"serialized\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"=\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" role.\"}),(0,n.jsx)(e.span,{style:{color:\"#B392F0\"},children:\"toString\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"();\"})]}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:\" \"}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\"/**\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * Note how you can pass in the Statements type again, to get full type safety\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" */\"})}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"const\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#79B8FF\"},children:\"recovered\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"=\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" Role.\"}),(0,n.jsx)(e.span,{style:{color:\"#B392F0\"},children:\"fromString\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"<\"}),(0,n.jsx)(e.span,{style:{color:\"#B392F0\"},children:\"Statements\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\">(serialized);\"})]}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:\" \"}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\"/**\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * Validate the role by specifying the resource and the required access\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" *\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" * everything is fully typed\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\" */\"})}),`\n`,(0,n.jsxs)(e.span,{className:\"line\",children:[(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"const\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#79B8FF\"},children:\"res\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" \"}),(0,n.jsx)(e.span,{style:{color:\"#F97583\"},children:\"=\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\" recovered.\"}),(0,n.jsx)(e.span,{style:{color:\"#B392F0\"},children:\"authorize\"}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"({\"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"team\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\", [\"}),(0,n.jsx)(e.span,{style:{color:\"#9ECBFF\"},children:'\"read\"'}),(0,n.jsx)(e.span,{style:{color:\"#E1E4E8\"},children:\"]});\"})]}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:\" \"}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\"// res.success => boolean\"})}),`\n`,(0,n.jsx)(e.span,{className:\"line\",children:(0,n.jsx)(e.span,{style:{color:\"#6A737D\"},children:\"// res.error => string | undefined provides a reason for failure\"})})]})})})]})}function A(l={}){let{wrapper:e}=l.components||{};return e?(0,n.jsx)(e,Object.assign({},l,{children:(0,n.jsx)(d,l)})):d(l)}var D=A;return f(B);})();\n;return Component;"
},
"_id": "projects/access.mdx",
"_raw": {
"sourceFilePath": "projects/access.mdx",
"sourceFileName": "access.mdx",
"sourceFileDir": "projects",
"contentType": "mdx",
"flattenedPath": "projects/access"
},
"type": "Project",
"path": "/projects/access",
"slug": "access"
}