text: (self.webpackChunkdocusaurus_template=self.webpackChunkdocusaurus_template||[]).push([[5203],{3905:function(e,t,n){"use strict";n.d(t,{Zo:function(){return p},kt:function(){return h}});var r=n(67294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?o(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):o(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function i(e,t){if(null==e)return{};var n,r,a=function(e,t){if(null==e)return{};var n,r,a={},o=Object.keys(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r<o.length;r++)n=o[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},p=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,c=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),d=l(n),h=a,f=d["".concat(c,".").concat(h)]||d[h]||u[h]||o;return n?r.createElement(f,s(s({ref:t},p),{},{components:n})):r.createElement(f,s({ref:t},p))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,s=new Array(o);s[0]=d;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:a,s[1]=i;for(var l=2;l<o;l++)s[l]=n[l];return r.createElement.apply(null,s)}return r.createElement.apply(null,n)}d.displayName="MDXCreateElement"},32527:function(e,t,n){"use strict";n.d(t,{Z:function(){return h}});var r=n(67294),a=n(21140),o=n.n(a),s="graph_1lrJ",i="pointer_3d8u",c="overlay_2fuY",l="visible_2Z3U",p="backdrop_2z5L",u=n(94184),d=n.n(u);o().initialize({startOnLoad:!0,logLevel:"fatal",securityLevel:"strict",arrowMarkerAbsolute:!1,theme:"neutral",flowchart:{useMaxWidth:!0,htmlLabels:!0,rankSpacing:65,nodeSpacing:30,curve:"basis"},sequence:{useMaxWidth:!0},gantt:{useMaxWidth:!0}});var h=function(e){var t,n=e.chart,a=(0,r.useState)(!1),u=a[0],h=a[1],f=(0,r.useState)(void 0),m=f[0],b=f[1],g=(0,r.useState)("mermaid-"+Math.random().toString(36).substr(2,-1))[0],v=function(){return h(!u)};return(0,r.useEffect)((function(){o().render(g,n,(function(e){b(e)}))}),[]),r.createElement(r.Fragment,null,r.createElement("div",{onClick:v,className:d()(s,i),dangerouslySetInnerHTML:{__html:m}}),r.createElement("div",{onClick:v,className:d()(c,i,s,(t={},t[l]=u,t))},r.createElement("div",{onClick:function(e){return e.stopPropagation()},className:d()(p,s),dangerouslySetInnerHTML:{__html:m}})))}},5429:function(e,t,n){"use strict";n.r(t),n.d(t,{frontMatter:function(){return i},contentTitle:function(){return c},metadata:function(){return l},toc:function(){return p},default:function(){return d}});var r=n(22122),a=n(19756),o=(n(67294),n(3905)),s=n(32527),i={title:"The Graph of Relations"},c=void 0,l={unversionedId:"concepts/graph-of-relations",id:"concepts/graph-of-relations",isDocsHomePage:!1,title:"The Graph of Relations",description:"The relation tuples of the ACL used by Ory Keto can be",source:"@site/docs/concepts/graph-of-relations.mdx",sourceDirName:"concepts",slug:"/concepts/graph-of-relations",permalink:"/keto/docs/next/concepts/graph-of-relations",editUrl:"https://github.com/ory/keto/edit/master/docs/docs/concepts/graph-of-relations.mdx",version:"current",lastUpdatedBy:"Patrik",lastUpdatedAt:1620720311,formattedLastUpdatedAt:"5/11/2021",frontMatter:{title:"The Graph of Relations"},sidebar:"docs",previous:{title:"Subjects",permalink:"/keto/docs/next/concepts/subjects"},next:{title:"API Overview",permalink:"/keto/docs/next/concepts/api-overview"}},p=[{value:"Definition",id:"definition",children:[]},{value:"Example",id:"example",children:[]},{value:"Observations about the Graph",id:"observations-about-the-graph",children:[]}],u={toc:p};function d(e){var t=e.components,n=(0,a.Z)(e,["components"]);return(0,o.kt)("wrapper",(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"The ",(0,o.kt)("a",{parentName:"p",href:"/keto/docs/next/concepts/relation-tuples"},"relation tuples")," of the ACL used by Ory Keto can be\nrepresented as a graph of relations. This graph will help us to understand many\n",(0,o.kt)("a",{parentName:"p",href:"/keto/docs/next/performance"},"implications on performance")," and\n",(0,o.kt)("a",{parentName:"p",href:"/keto/docs/next/concepts/internal-algorithms"},"internal algorithms"),"."),(0,o.kt)("h2",{id:"definition"},"Definition"),(0,o.kt)("p",null,"The graph consists of three types of nodes. ",(0,o.kt)("a",{parentName:"p",href:"/keto/docs/next/concepts/objects"},"Object")," nodes that\nrepresent application objects, intermediary\n",(0,o.kt)("a",{parentName:"p",href:"/keto/docs/next/concepts/subjects#subject-sets"},"subject set")," nodes, and\n",(0,o.kt)("a",{parentName:"p",href:"/keto/docs/next/concepts/subjects#subject-ids"},"subject ID")," nodes representing individuals. Edges\nare directed and represent the relation between an object and subject."),(0,o.kt)("h2",{id:"example"},"Example"),(0,o.kt)("p",null,"The following example translates a view relation tuples into the corresponding\ngraph of relations."),(0,o.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,o.kt)("div",{parentName:"div",className:"admonition-heading"},(0,o.kt)("h5",{parentName:"div"},(0,o.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,o.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,o.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"note")),(0,o.kt)("div",{parentName:"div",className:"admonition-content"},(0,o.kt)("p",{parentName:"div"},"This example omits the ",(0,o.kt)("a",{parentName:"p",href:"/keto/docs/next/concepts/namespaces"},"namespace")," from all data to improve\nreadability. In practice, the namespace always has to be considered."))),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-keto-relation-tuples"},"// user1 has access on dir1\ndir1#access@user1\n// Have a look on the subjects concept page if you don't know the empty relation.\ndir1#child@(file1#)\n// Everyone with access to dir1 has access to file1. This would probably be defined\n// through a subject set rewrite that defines this inherited relation globally.\n// In this example, we define this tuple explicitly.\nfile1#access@(dir1#access)\n// Direct access on file2 was granted.\nfile2#access@user1\n// user2 is owner of file2\nfile2#owner@user2\n// Owners of file2 have access to it; possibly defined through subject set rewrites.\nfile2#access@(file2#owner)\n")),(0,o.kt)("p",null,"This is represented by the following graph:"),(0,o.kt)(s.Z,{chart:"\ngraph TD\n    subgraph obj [Object region]\n    E[dir1]\n    A[file1] --\x3e|child| E\n    G[file2]\n    end\n    subgraph subjID [Subject ID region]\n    F([user1])\n    C([user2])\n    end\n    A --\x3e|access| B{{dir1#access}}\n    B -. file1#access .-> F\n    E --\x3e|access| F\n    G --\x3e|access| F\n    G --\x3e|owner| C\n    G --\x3e|access| H{{file2#owner}}\n    H -. file2#access .-> C\n",mdxType:"Mermaid"}),(0,o.kt)("p",null,"Solid edges represent explicitly defined relations, while dotted edges represent\nrelations inherited through a subject set."),(0,o.kt)("h2",{id:"observations-about-the-graph"},"Observations about the Graph"),(0,o.kt)("p",null,"Ory Keto utilizes the following key properties of the graph of relations:"),(0,o.kt)("ol",null,(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("strong",{parentName:"li"},"Directed edges from objects to subjects"),": This implies a neat arrangement\nwith objects in one region, subject IDs in another one, and subject sets in\nbetween. Edges will always go from the object region towards the subject\nregion."),(0,o.kt)("li",{parentName:"ol"},(0,o.kt)("strong",{parentName:"li"},"Searching for a possible path is local"),": Trying to find a path from an\nobject to a subject will always happen locally. This means that it is only\nnecessary to traverse the nodes that are successors of the object. In typical\nsetups, this means that only a small fraction of the graph has to be\nsearched, regardless of the outcome. The intuition here is that the relations\nof user1's files are irrelevant when checking access to user2's files.")),(0,o.kt)("p",null,"Both of these properties are important to ensure\n",(0,o.kt)("a",{parentName:"p",href:"/keto/docs/next/performance"},"high performance"),"."))}d.isMDXComponent=!0},11748:function(e,t,n){var r={"./locale":89234,"./locale.js":89234};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=11748}}]);