PageSourceSearch

https://feathers-casl.netlify.app/getting-started

html feathers-casl.netlify.app collected 2026-10-03 10:43:40 UTC 67,161 bytes, 218 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en-US" dir="ltr">
3  <head>
4    <meta charset="utf-8">
5    <meta name="viewport" content="width=device-width,initial-scale=1">
6    <title>Getting Started | feathers-casl</title>
7    <meta name="description" content="Add access control with CASL to your feathers application">
8    <meta name="generator" content="VitePress v2.0.0-alpha.17">
9    <link rel="preload stylesheet" href="/assets/style.BUHdsUFN.css" as="style">
10    <link rel="preload stylesheet" href="/vp-icons.css" as="style">
11    
12    
12<script type="module" src="/assets/app.CwQ1rY3O.js"></script>
12
13    <link rel="preload" href="/assets/inter-roman-latin.Cy4MYw_J.woff2" as="font" type="font/woff2" crossorigin="">
14    <link rel="modulepreload" href="/assets/chunks/theme.BsDwXA-J.js">
15    <link rel="modulepreload" href="/assets/chunks/framework.DWIwSZ-6.js">
16    <link rel="modulepreload" href="/assets/getting-started.md.BlL7VB7m.lean.js">
17    <link rel="icon" href="/favicon.ico">
18    
18<script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
18
19    
19<script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
19
20  </head>
21  <body>
22    <div id="app"><div class="Layout" data-v-7ee4747a><!--[--><!--]--><!--[--><span tabindex="-1" data-v-56ddb84b></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-56ddb84b>Skip to content</a><!--]--><!----><header class="VPNav" data-v-7ee4747a data-v-8187dc6d><div class="VPNavBar has-sidebar top" data-v-8187dc6d data-v-17451696><div class="wrapper" data-v-17451696><div class="container" data-v-17451696><div class="title" data-v-17451696><div class="VPNavBarTitle has-sidebar" data-v-17451696 data-v-7f767ae5><a class="title" href="/" data-v-7f767ae5><!--[--><!--]--><!--[--><img class="VPImage logo" src="/img/logo.svg" alt data-v-f9fc7ca2><!--]--><span data-v-7f767ae5>feathers-casl</span><!--[--><!--]--></a></div></div><div class="content" data-v-17451696><div class="content-body" data-v-17451696><!--[--><!--]--><div class="VPNavBarSearch search" data-v-17451696 data-v-b115b792><!--[--><button type="button" class="VPNavBarSearchButton" aria-label="Search" aria-keyshortcuts="/ control+k meta+k" data-v-b115b792 data-v-32351076><span class="vpi-search" aria-hidden="true" data-v-32351076></span><span class="text" data-v-32351076>Search</span><span class="keys" aria-hidden="true" data-v-32351076><kbd class="key-cmd" data-v-32351076>⌘</kbd><kbd class="key-ctrl" data-v-32351076>Ctrl</kbd><kbd data-v-32351076>K</kbd></span></button><!----><!----><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-17451696 data-v-b1964aab><span id="main-nav-aria-label" class="visually-hidden" data-v-b1964aab> Main Navigation </span><!--[--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-b1964aab data-v-48018a98><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-48018a98><span class="text" data-v-48018a98><!----><span data-v-48018a98>Ecosystem</span><span class="vpi-chevron-down text-icon" data-v-48018a98></span></span></button><div class="menu" data-v-48018a98><div class="VPMenu" data-v-48018a98 data-v-e21def72><div class="items" data-v-e21def72><!--[--><!--[--><div class="VPMenuLink" data-v-e21def72 data-v-328078e2><a class="VPLink link vp-external-link-icon" href="https://feathersjs.com/" target="_blank" rel="noreferrer" data-v-328078e2><!--[--><span data-v-328078e2>www.feathersjs.com</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-e21def72 data-v-328078e2><a class="VPLink link vp-external-link-icon" href="https://github.com/feathersjs/feathers" target="_blank" rel="noreferrer" data-v-328078e2><!--[--><span data-v-328078e2>Feathers Github Repo</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-e21def72 data-v-328078e2><a class="VPLink link vp-external-link-icon" href="https://github.com/feathersjs/awesome-feathersjs" target="_blank" rel="noreferrer" data-v-328078e2><!--[--><span data-v-328078e2>Awesome Feathersjs</span><!--]--></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-17451696 data-v-d0e9ddd6><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-d0e9ddd6 data-v-88d2d789 data-v-9ae567d2><span class="check" data-v-9ae567d2><span class="icon" data-v-9ae567d2><!--[--><span class="vpi-sun sun" data-v-88d2d789></span><span class="vpi-moon moon" data-v-88d2d789></span><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-17451696 data-v-b2135855 data-v-31833492><!--[--><a class="VPSocialLink no-icon" href="https://twitter.com/feathersjs" aria-label="twitter" target="_blank" rel="me noopener" data-v-31833492 data-v-fd5e6b74><span class="vpi-social-twitter"></span></a><a class="VPSocialLink no-icon" href="https://discord.gg/qa8kez8QBx" aria-label="discord" target="_blank" rel="me noopener" data-v-31833492 data-v-fd5e6b74><span class="vpi-social-discord"></span></a><a class="VPSocialLink no-icon" href="https://github.com/fratzinger/feathers-casl" aria-label="github" target="_blank" rel="me noopener" data-v-31833492 data-v-fd5e6b74><span class="vpi-social-github"></span></a>
22<!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-17451696 data-v-339e20dc data-v-48018a98><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-48018a98><span class="vpi-more-horizontal icon" data-v-48018a98></span></button><div class="menu" data-v-48018a98><div class="VPMenu" data-v-48018a98 data-v-e21def72><!----><!--[--><!--[--><!----><div class="group" data-v-339e20dc><div class="item appearance" data-v-339e20dc><p class="label" data-v-339e20dc>Appearance</p><div class="appearance-action" data-v-339e20dc><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-339e20dc data-v-88d2d789 data-v-9ae567d2><span class="check" data-v-9ae567d2><span class="icon" data-v-9ae567d2><!--[--><span class="vpi-sun sun" data-v-88d2d789></span><span class="vpi-moon moon" data-v-88d2d789></span><!--]--></span></span></button></div></div></div><div class="group" data-v-339e20dc><div class="item social-links" data-v-339e20dc><div class="VPSocialLinks social-links-list" data-v-339e20dc data-v-31833492><!--[--><a class="VPSocialLink no-icon" href="https://twitter.com/feathersjs" aria-label="twitter" target="_blank" rel="me noopener" data-v-31833492 data-v-fd5e6b74><span class="vpi-social-twitter"></span></a><a class="VPSocialLink no-icon" href="https://discord.gg/qa8kez8QBx" aria-label="discord" target="_blank" rel="me noopener" data-v-31833492 data-v-fd5e6b74><span class="vpi-social-discord"></span></a><a class="VPSocialLink no-icon" href="https://github.com/fratzinger/feathers-casl" aria-label="github" target="_blank" rel="me noopener" data-v-31833492 data-v-fd5e6b74><span class="vpi-social-github"></span></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-17451696 data-v-25aec7de><span class="container" data-v-25aec7de><span class="top" data-v-25aec7de></span><span class="middle" data-v-25aec7de></span><span class="bottom" data-v-25aec7de></span></span></button></div></div></div></div><div class="divider" data-v-17451696><div class="divider-line" data-v-17451696></div></div></div><!----></header><div class="VPLocalNav has-sidebar empty" data-v-7ee4747a data-v-8f3272e2><div class="container" data-v-8f3272e2><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-8f3272e2><span class="vpi-align-left menu-icon" data-v-8f3272e2></span><span class="menu-text" data-v-8f3272e2>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-8f3272e2 data-v-1cceb885><button data-v-1cceb885>Return to top</button><!----></div></div></div><aside class="VPSidebar" data-v-7ee4747a data-v-3151ed93><div class="curtain" data-v-3151ed93></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-3151ed93><span class="visually-hidden" id="sidebar-aria-label" data-v-3151ed93> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="no-transition group" data-v-862074ed><section class="VPSidebarItem level-0 has-active" data-v-862074ed data-v-9957c532><div class="item" role="button" tabindex="0" data-v-9957c532><div class="indicator" data-v-9957c532></div><h2 class="text" data-v-9957c532>Guide</h2><!----></div><div class="items" data-v-9957c532><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9957c532><div class="item" data-v-9957c532><div class="indicator" data-v-9957c532></div><a class='VPLink link link' data-v-9957c532 href='/getting-started'><!--[--><p class="text" data-v-9957c532>Getting Started</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9957c532><div class="item" data-v-9957c532><div class="indicator" data-v-9957c532></div><a class='VPLink link link' data-v-9957c532 href='/hooks'><!--[--><p class="text" data-v-9957c532>Hooks</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9957c532><div class="item" data-v-9957c532><div class="indicator" data-v-9957c532></div><a class='VPLink link link' data-v-9957c532 href='/channels'><!--[--><p class="text" data-v-9957c532>Channels</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9957c532><div class="item" data-v-9957c532><div class="indicator" data-v-9957c532></div><a class='VPLink link link' data-v-9957c532 href='/utils'><!--[--><p class="text" data-v-9957c532>Utils</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9957c532><div class="item" data-v-9957c532><div class="indicator" data-v-9957c532></div><a class='VPLink link link' data-v-9957c532 href='/client-side'><!--[--><p class="text" data-v-9957c532>Client Side</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9957c532><div class="item" data-v-9957c532><div class="indicator" data-v-9957c532></div><a class='VPLink link link' data-v-9957c532 href='/gotchas'><!--[--><p class="text" data-v-9957c532>Gotchas</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9957c532><div class="item" data-v-9957c532><div class="indicator" data-v-9957c532></div><a class='VPLink link link' data-v-9957c532 href='/cookbook'><!--[--><p class="text" data-v-9957c532>Cookbook</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-7ee4747a data-v-70980a40><div class="VPDoc has-sidebar has-aside" data-v-70980a40 data-v-7da62fb4><!--[--><!--]--><div class="container" data-v-7da62fb4><div class="aside" data-v-7da62fb4><div class="aside-curtain" data-v-7da62fb4></div><div class="aside-container" data-v-7da62fb4><div class="aside-content" data-v-7da62fb4><div class="VPDocAside" data-v-7da62fb4 data-v-7808de11><!--[--><!--]--><!--[--><!--]--><nav aria-labelledby="doc-outline-aria-label" class="VPDocAsideOutline" data-v-7808de11 data-v-3c649ff1><div class="content" data-v-3c649ff1><div class="outline-marker" data-v-3c649ff1></div><div aria-level="2" class="outline-title" id="doc-outline-aria-label" role="heading" data-v-3c649ff1>On this page</div><ul class="VPDocOutlineItem root" data-v-3c649ff1 data-v-a8515184><!--[--><!--]--></ul></div></nav><!--[--><!--]--><div class="spacer" data-v-7808de11></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-7da62fb4><div class="content-container" data-v-7da62fb4><!--[--><!--]--><main class="main" data-v-7da62fb4><div style="position:relative;" class="vp-doc _getting-started" data-v-7da62fb4><div>
22<h1 id="getting-started" tabindex="-1">Getting Started <a class="header-anchor" href="#getting-started" aria-label="Permalink to “Getting Started”">​</a></h1><p align="center"><img src="/img/logo.svg" width="150"></p><p><a href="https://www.npmjs.com/package/feathers-casl" target="_blank" rel="noreferrer"><img src="https://img.shields.io/npm/v/feathers-casl" alt="npm"></a><a href="https://github.com/fratzinger/feathers-casl/actions" target="_blank" rel="noreferrer"><img src="https://github.com/fratzinger/feathers-casl/actions/workflows/node.js.yml/badge.svg" alt="Github CI"></a><a href="https://codeclimate.com/github/fratzinger/feathers-casl" target="_blank" rel="noreferrer"><img src="https://img.shields.io/codeclimate/maintainability/fratzinger/feathers-casl" alt="Code Climate maintainability"></a><a href="https://codeclimate.com/github/fratzinger/feathers-casl" target="_blank" rel="noreferrer"><img src="https://img.shields.io/codeclimate/coverage/fratzinger/feathers-casl" alt="Code Climate coverage"></a><a href="https://libraries.io/npm/feathers-casl" target="_blank" rel="noreferrer"><img src="https://img.shields.io/librariesio/release/npm/feathers-casl" alt="libraries.io"></a><a href="https://www.npmjs.com/package/feathers-casl" target="_blank" rel="noreferrer"><img src="https://img.shields.io/npm/dm/feathers-casl" alt="npm"></a><a href="https://github.com/fratzinger/feathers-casl/blob/main/LICENSE" target="_blank" rel="noreferrer"><img src="https://img.shields.io/github/license/fratzinger/feathers-casl" alt="GitHub license"></a><a href="https://discord.gg/qa8kez8QBx" target="_blank" rel="noreferrer"><img src="https://badgen.net/badge/icon/discord?icon=discord&amp;label" alt="Discord"></a></p><h2 id="about" tabindex="-1">About <a class="header-anchor" href="#about" aria-label="Permalink to “About”">​</a></h2><p>Add access control with CASL to your feathers application.</p><p>This project is built for <a href="http://feathersjs.com" target="_blank" rel="noreferrer">FeathersJS</a>. An open source web framework for building modern real-time applications. It&#39;s based on <a href="https://casl.js.org/" target="_blank" rel="noreferrer">CASL</a> and is a convenient layer to use <strong>CASL</strong> in your feathers.js-project. Supported versions: <code>@casl/ability^6</code> and <code>@feathersjs/feathers^5</code>.</p><h2 id="features" tabindex="-1">Features <a class="header-anchor" href="#features" aria-label="Permalink to “Features”">​</a></h2><ul><li>Fully powered by Feathers 5 &amp; CASL 6</li><li>Allows permissions for all methods <code>create</code>, <code>find</code>, <code>get</code>, <code>update</code>, <code>patch</code>, <code>remove</code>, or <code>create</code>, <code>read</code>, <code>update</code>, <code>delete</code></li><li>Define permissions not based on methods: <code>can(&#39;view&#39;, &#39;Settings&#39;)</code> (Bring your custom logic)</li><li>Restrict by conditions: <code>can(&#39;create&#39;, &#39;Task&#39;, { userId: user.id })</code></li><li>Restrict by individual fields: <code>cannot(&#39;update&#39;, &#39;User&#39;, [&#39;roleId&#39;])</code></li><li>Native support for restrictive <code>$select</code>: <code>can(&#39;read&#39;, &#39;User&#39;, [&#39;id&#39;, &#39;username&#39;])</code> -&gt; <code>$select: [&#39;id&#39;, &#39;username&#39;]</code></li><li>Support to define abilities for anything (providers, users, roles, 3rd party apps, ...)</li><li>Fully supported adapters: <code>@feathersjs/knex</code>, <code>@feathersjs/memory</code>, <code>@feathersjs/mongodb</code>, <code>@fratzinger/feathers-kysely</code>, <code>feathers-sequelize</code>, not supported: <code>feathers-mongoose</code>, <code>feathers-nedb</code>, <code>feathers-objection</code></li><li>Support for dynamic rules stored in your database (Bring your own implementation 😉 )</li><li>hooks: <ul><li><code>checkBasicPermission</code> hook for client side usage as a before-hook</li><li><code>authorize</code> hook for complex rules</li><li>Disallow/allow <code>multi</code> methods (<code>create</code>, <code>patch</code>, <code>remove</code>) dynamically with: <code>can(&#39;remove-multi&#39;, &#39;Task&#39;, { userId: user.id })</code></li></ul></li><li>channels: <ul><li>every connection only receives updates based on rules</li><li><code>channels</code>-support also regards restrictive fields</li><li>rules can be defined individually for events</li></ul></li><li>utils: <ul><li><code>checkCan</code> to be used in hooks to check authorization before operations</li></ul></li><li>Baked in support for <code>@casl/angular</code>, <code>@casl/react</code>, <code>@casl/vue</code> and <code>@casl/aurelia</code></li></ul><h2 id="installation" tabindex="-1">Installation <a class="header-anchor" href="#installation" aria-label="Permalink to “Installation”">​</a></h2><div class="language-bash"><button title="Copy Code" class="copy"></button><span class="lang">bash</span>
22<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># npm</span></span>
23<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">npm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> i</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> feathers-casl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @casl/ability</span></span>
24<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># yarn</span></span>
25<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">yarn</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> add</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> feathers-casl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @casl/ability</span></span>
26<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"># pnpm</span></span>
27<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pnpm</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> i</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> feathers-casl</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> @casl/ability</span></span></code></pre></div><h2 id="getting-started-1" tabindex="-1">Getting Started <a class="header-anchor" href="#getting-started-1" aria-label="Permalink to “Getting Started”">​</a></h2><h3 id="provide-app-wide-feathers-casl-options" tabindex="-1">Provide app wide <code>feathers-casl</code> options <a class="header-anchor" href="#provide-app-wide-feathers-casl-options" aria-label="Permalink to “Provide app wide feathers-casl options”">​</a></h3><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// app.ts</span></span>
28<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { feathersCasl } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;feathers-casl&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
29<span class="line"></span>
30<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">configure</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">feathersCasl</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">());</span></span></code></pre></div><p>The <code>feathersCasl()</code> function can be configured, to provide app wide options to <code>feathers-casl</code></p><h3 id="define-static-rules" tabindex="-1">Define static rules <a class="header-anchor" href="#define-static-rules" aria-label="Permalink to “Define static rules”">​</a></h3><p>For most cases we want to define rules per user (or per user-role). So we first add a function which returns an <code>ability</code> from <code>@casl/ability</code> with these rules:</p><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/services/authentication/authentication.abilities.ts</span></span>
31<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">
31import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { Ability, AbilityBuilder, createAliasResolver } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@casl/ability&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
32<span class="line"></span>
33<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// don&#39;t forget this, as `read` is used internally</span></span>
34<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> resolveAction</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createAliasResolver</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
35<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  update: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;patch&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// define the same rules for update &amp; patch</span></span>
36<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  read: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;get&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;find&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// use &#39;read&#39; as a equivalent for &#39;get&#39; &amp; &#39;find&#39;</span></span>
37<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  delete: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;remove&quot;</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // use &#39;delete&#39; or &#39;remove&#39;</span></span>
38<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
39<span class="line"></span>
40<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineRulesFor</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
41<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // also see https://casl.js.org/v6/en/guide/define-rules</span></span>
42<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">can</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">cannot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">rules</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AbilityBuilder</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(Ability);</span></span>
43<span class="line"></span>
44<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (user.role </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> user.role.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;SuperAdmin&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
45<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">    // SuperAdmin can do evil</span></span>
46<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">    can</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;manage&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;all&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
47<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> rules;</span></span>
48<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  }</span></span>
49<span class="line"></span>
50<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (user.role </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> user.role.name </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;Admin&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
51<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">    can</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;create&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;users&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
52<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  }</span></span>
53<span class="line"></span>
54<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">  can</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;read&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;users&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
55<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">  can</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;update&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;users&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { id: user.id });</span></span>
56<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">  cannot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;update&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;users&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">
56, [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;roleId&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], { id: user.id });</span></span>
57<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">  cannot</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;delete&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;users&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { id: user.id });</span></span>
58<span class="line"></span>
59<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">  can</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;manage&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;tasks&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { userId: user.id });</span></span>
60<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">  can</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;create-multi&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;posts&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { userId: user.id });</span></span>
61<span class="line"></span>
62<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> rules;</span></span>
63<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span>
64<span class="line"></span>
65<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAbilitiesFor</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
66<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> rules</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineRulesFor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(user);</span></span>
67<span class="line"></span>
68<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  return</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Ability</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(rules, { resolveAction });</span></span>
69<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h3 id="add-abilities-to-hooks-context" tabindex="-1">Add abilities to hooks context <a class="header-anchor" href="#add-abilities-to-hooks-context" aria-label="Permalink to “Add abilities to hooks context”">​</a></h3><p><code>feathers-casl</code> by default looks for <code>context.params.ability</code> in the <code>authorize</code>-hook and <code>connection.ability</code> in the channels. You want to <code>authorize</code> users who are <code>authenticated</code> first with <code>@feathers/authentication</code>. We can add hooks to the <code>/authentication</code> service to populate things to <code>context.params</code> and <code>connection</code> under the hood. We use this here to put <code>ability</code> on these objects, which makes it available to all hooks after the <code>authenticate(...)</code>-hook. This way we can define rules in just one place: ``</p><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span>
69<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/services/authentication/authentication.hooks.ts</span></span>
70<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { defineAbilitiesFor } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;./abilities&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
71<span class="line"></span>
72<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
73<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  before: {</span></span>
74<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    all: [],</span></span>
75<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    find: [],</span></span>
76<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    get: [],</span></span>
77<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    create: [],</span></span>
78<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    update: [],</span></span>
79<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    patch: [],</span></span>
80<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    remove: []</span></span>
81<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  },</span></span>
82<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  after: {</span></span>
83<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    all: [],</span></span>
84<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    find: [],</span></span>
85<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    get: [],</span></span>
86<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    create: [</span></span>
87<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
88<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">        const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> context.result;</span></span>
89<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">user) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> context;</span></span>
90<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">        const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> ability</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAbilitiesFor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(user);</span></span>
91<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        context.result.ability </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ability;</span></span>
92<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        context.result.rules </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ability.rules;</span></span>
93<span class="line"></span>
94<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> context;</span></span>
95<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      }</span></span>
96<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    ],</span></span>
97<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    update: [],</span></span>
98<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    patch: [],</span></span>
99<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    remove: []</span></span>
100<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  },</span></span>
101<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  error: {</span></span>
102<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    all: [],</span></span>
103<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    find: [],</span></span>
104<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    get: [],</span></span>
105<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    create: [],</span></span>
106<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    update: [],</span></span>
107<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    patch: [],</span></span>
108<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    remove: []</span></span>
109<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  }</span></span>
110<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};
110</span></span></code></pre></div><h3 id="add-the-authorize-hook-to-the-services" tabindex="-1">Add the authorize-hook to the services <a class="header-anchor" href="#add-the-authorize-hook-to-the-services" aria-label="Permalink to “Add the authorize-hook to the services”">​</a></h3><p>The <code>authorize</code>-hook can be used for all methods and has support for <code>multi: true</code>. You should use it as a <code>before</code> <strong>AND</strong> a <code>after</code> hook at the same time. For more information, see: <a href='/hooks#authorize'>authorize hook</a></p><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/services/tasks/tasks.hooks.ts</span></span>
111<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { authenticate } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;@feathersjs/authentication&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
112<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { authorize } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;feathers-casl&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
113<span class="line"></span>
114<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// CAUTION! Make sure the adapter name fits your adapter (e.g. @feathersjs/mongodb, @feathersjs/knex, @fratzinger/feathers-kysely, feathers-sequelize, ...)!</span></span>
115<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// You&#39;ll want to have the `authorize` as an early before-hook (right after the `authenticate` hook) and as a late after hook, since it could modify the result based on the ability of the requesting user</span></span>
116<span class="line"></span>
117<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> authorizeHook</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> authorize</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ adapter: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;@feathersjs/mongodb&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> });</span></span>
118<span class="line"></span>
119<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
120<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  before: {</span></span>
121<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    all: [</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">authenticate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;jwt&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)],</span></span>
122<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    find: [authorizeHook],</span></span>
123<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    get: [authorizeHook],</span></span>
124<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    create: [authorizeHook],</span></span>
125<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    update: [authorizeHook],</span></span>
126<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    patch: [authorizeHook],</span></span>
127<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    remove: [authorizeHook]</span></span>
128<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  },</span></span>
129<span class="line"></span>
130<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  after: {</span></span>
131<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    all: [authorizeHook],</span></span>
132<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    find: [],</span></span>
133<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    get: [],</span></span>
134<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    create: [],</span></span>
135<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    update: [],</span></span>
136<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    patch: [],</span></span>
137<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    remove: []</span></span>
138<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  },</span></span>
139<span class="line"></span>
140<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  error: {</span></span>
141<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    all: [],</span></span>
142<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    find: [],</span></span>
143<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    get: [],</span></span>
144<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    create: [],</span></span>
145<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    update: [],</span></span>
146<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    patch: [],</span></span>
147<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    remove: []</span></span>
148<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  }</span></span>
149<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};
149</span></span></code></pre></div><h3 id="filters-operators" tabindex="-1">Filters / Operators <a class="header-anchor" href="#filters-operators" aria-label="Permalink to “Filters / Operators”">​</a></h3><p>For <code>feathers-casl</code> to work properly, you have to whitelist some operators in your service options. Also make sure to set the adapter option in your <code>authorize</code> hook like: <code>authorize({ adapter: &#39;@feathersjs/mongodb&#39; })</code></p><p><code>feathers-casl</code> merges the conditions of your rules into the incoming query. Inverted rules (<code>cannot(...)</code>) are expressed with <code>$nor</code>/<code>$not</code>, and whenever a rule condition and the query restrict the same property, both are combined with <code>$and</code>. Your service has to allow these operators:</p><ul><li><strong>@feathersjs/memory</strong>: <code>app.use(&#39;...&#39;, new Service({ filters: { $nor: true }, operators: [&quot;$nor&quot;, &quot;$and&quot;] }))</code></li><li><strong>@feathersjs/mongodb</strong>: <code>app.use(&#39;...&#39;, new Service({ filters: { $nor: true }, operators: [&quot;$nor&quot;, &quot;$and&quot;] }))</code></li><li><strong>@feathersjs/knex</strong>: nothing special to configure 😃</li><li><strong>@fratzinger/feathers-kysely</strong>: expresses inverted (<code>cannot</code>) rules with <code>$not</code>, so this operator has to be allowed: <code>app.use(&#39;...&#39;, new KyselyService({ filters: { $not: true }, operators: [&quot;$not&quot;, &quot;$and&quot;] }))</code></li><li><strong>feathers-sequelize</strong>: This one is a little bit different than the others. See the following:</li></ul><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { SequelizeService } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;feathers-sequelize&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
150<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { Op } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;sequelize&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
151<span class="line"></span>
152<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// ...</span></span>
153<span class="line"></span>
154<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">use</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
155<span class="line"><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">  &quot;...&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
156<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> SequelizeService</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
157<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    Model,</span></span>
158<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    operatorMap: {</span></span>
159<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      $not: Op.not</span></span>
160<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    },</span></span>
161<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    filters: {</span></span>
162<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      $not: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span></span>
163<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    },</span></span>
164<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    operators: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;$not&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]</span></span>
165<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  })</span></span>
166<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span></code></pre></div><h3 id="add-casl-to-channels" tabindex="-1">Add CASL to channels <a class="header-anchor" href="#add-casl-to-channels" aria-label="Permalink to “Add CASL to channels”">​</a></h3><p>To unleash the full power of <code>feathers-casl</code> you want to add it to your <code>channels.js</code> so every user just gets updates only to items they can really read. It&#39;s as simple as the following example. For more information see: <a href='/channels'>channels</a></p><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span>
166<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/channels.ts</span></span>
167<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { getChannelsWithReadAbility, makeChannelOptions } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;feathers-casl&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
168<span class="line"></span>
169<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> function</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">app</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
170<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> app.channel </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">!==</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;function&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
171<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">    // If no real-time functionality has been configured just return</span></span>
172<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
173<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  }</span></span>
174<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // ...</span></span>
175<span class="line"></span>
176<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">on</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;login&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">authResult</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">connection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
177<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (connection) {</span></span>
178<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">      // this is needed to map the ability from the authentication hook to the connection so it gets available in the HookContext as `params.ability` automatically</span></span>
179<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">      if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (authResult.ability) {</span></span>
180<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        connection.ability </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> authResult.ability;</span></span>
181<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        connection.rules </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> authResult.rules;</span></span>
182<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      }</span></span>
183<span class="line"></span>
184<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">
184      // ...</span></span>
185<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    }</span></span>
186<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  });</span></span>
187<span class="line"></span>
188<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // ...</span></span>
189<span class="line"></span>
190<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> caslOptions</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> makeChannelOptions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(app);</span></span>
191<span class="line"></span>
192<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">publish</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
193<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">    return</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> getChannelsWithReadAbility</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(app, data, context, caslOptions);</span></span>
194<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  });</span></span>
195<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h3 id="using-casl-with-the-rest-express-js-transport" tabindex="-1">Using CASL with the REST (Express.js) transport <a class="header-anchor" href="#using-casl-with-the-rest-express-js-transport" aria-label="Permalink to “Using CASL with the REST (Express.js) transport”">​</a></h3><p>In case you are not using sockets and want to use <code>feathers-casl</code> with the Express transport, you need to define the abilities right after your <code>authenticate()</code> hook and before the <code>authorize()</code> hook for each service relying on CASL.</p><div class="language-ts"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e;" tabindex="0" dir="ltr"><code><span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// src/services/tasks/tasks.hooks.ts</span></span>
196<span class="line"></span>
197<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
198<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  before: {</span></span>
199<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    all: [</span></span>
200<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">      authenticate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;jwt&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
201<span class="line"></span>
202<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">      // Add this to set abilities, if a user exists</span></span>
203<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      (</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">context</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
204<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">        const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> context.params;
204</span></span>
205<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (user) context.params.ability </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> defineAbilitiesFor</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(user);</span></span>
206<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> context;</span></span>
207<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      }</span></span>
208<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    ]</span></span>
209<span class="line"></span>
210<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">    // ...</span></span>
211<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  }</span></span>
212<span class="line"></span>
213<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // ...</span></span>
214<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">};</span></span></code></pre></div><h2 id="testing" tabindex="-1">Testing <a class="header-anchor" href="#testing" aria-label="Permalink to “Testing”">​</a></h2><p>Simply run <code>npm test</code> and all your tests in the <code>test/</code> directory will be run. The project has full support for <em>Visual Studio Code</em>. You can use the debugger to set breakpoints.</p><h2 id="help" tabindex="-1">Help <a class="header-anchor" href="#help" aria-label="Permalink to “Help”">​</a></h2><p>For more information on all the things you can do, visit <a href="http://docs.feathersjs.com" target="_blank" rel="noreferrer">FeathersJS</a> and <a href="https://casl.js.org/v6/en/" target="_blank" rel="noreferrer">CASL</a>.</p></div></div></main><footer class="VPDocFooter" data-v-7da62fb4 data-v-cec3e6e5><!--[--><!--]--><div class="edit-info" data-v-cec3e6e5><div class="edit-link" data-v-cec3e6e5><a class="VPLink link vp-external-link-icon no-icon edit-link-button" href="https://github.com/fratzinger/feathers-casl/edit/main/docs/getting-started.md" target="_blank" rel="noreferrer" data-v-cec3e6e5><!--[--><span class="vpi-square-pen edit-link-icon" data-v-cec3e6e5></span> Edit this page on GitHub<!--]--></a></div><!----></div><nav class="prev-next" aria-labelledby="doc-footer-aria-label" data-v-cec3e6e5><span class="visually-hidden" id="doc-footer-aria-label" data-v-cec3e6e5>Pager</span><div class="pager" data-v-cec3e6e5><!----></div><div class="pager" data-v-cec3e6e5><a class='VPLink link pager-link next' data-v-cec3e6e5 href='/hooks'><!--[--><span class="desc" data-v-cec3e6e5>Next page</span><span class="title" data-v-cec3e6e5>Hooks</span><!--]--></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><footer class="VPFooter has-sidebar" data-v-7ee4747a data-v-7325e293><div class="container" data-v-7325e293><p class="message" data-v-7325e293>Released under the MIT License.</p><p class="copyright" data-v-7325e293>Copyright © 2020-present Frederik Schmatz<br />This site is powered by <a href="https://www.netlify.com" target="blank">Netlify</a></p></div></footer><!--[--><!--]--></div></div>
215    
215<script>window.__VP_HASH_MAP__=JSON.parse("{\"channels.md\":\"O1CseBp_\",\"client-side.md\":\"BIKoN4Mz\",\"cookbook.md\":\"CgOHqBSA\",\"getting-started.md\":\"BlL7VB7m\",\"gotchas.md\":\"BPwWJOEX\",\"hooks.md\":\"BF0jEmHj\",\"index.md\":\"Btq2ebLl\",\"utils.md\":\"CXwUvBvW\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"feathers-casl\",\"description\":\"Add access control with CASL to your feathers application\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"logo\":\"/img/logo.svg\",\"editLink\":{\"pattern\":\"https://github.com/fratzinger/feathers-casl/edit/main/docs/:path\",\"text\":\"Edit this page on GitHub\"},\"lastUpdatedText\":\"Last Updated\",\"socialLinks\":[{\"icon\":\"twitter\",\"link\":\"https://twitter.com/feathersjs\"},{\"icon\":\"discord\",\"link\":\"https://discord.gg/qa8kez8QBx\"},{\"icon\":\"github\",\"link\":\"https://github.com/fratzinger/feathers-casl\"}],\"sidebar\":[{\"text\":\"Guide\",\"items\":[{\"text\":\"Getting Started\",\"link\":\"/getting-started\"},{\"text\":\"Hooks\",\"link\":\"/hooks\"},{\"text\":\"Channels\",\"link\":\"/channels\"},{\"text\":\"Utils\",\"link\":\"/utils\"},{\"text\":\"Client Side\",\"link\":\"/client-side\"},{\"text\":\"Gotchas\",\"link\":\"/gotchas\"},{\"text\":\"Cookbook\",\"link\":\"/cookbook\"}]}],\"nav\":[{\"text\":\"Ecosystem\",\"items\":[{\"text\":\"www.feathersjs.com\",\"link\":\"https://feathersjs.com/\"},{\"text\":\"Feathers Github Repo\",\"link\":\"https://github.com/feathersjs/feathers\"},{\"text\":\"Awesome Feathersjs\",\"link\":\"https://github.com/feathersjs/awesome-feathersjs\"}]}],\"footer\":{\"message\":\"Released under the MIT License.\",\"copyright\":\"Copyright © 2020-present Frederik Schmatz<br />This site is powered by <a href=\\\"https://www.netlify.com\\\" target=\\\"blank\\\">Netlify</a>\"},\"search\":{\"provider\":\"algolia\",\"options\":{\"appId\":\"XJKV0V1N7U\",\"apiKey\":\"a4c3e7c6c2fcd7b1baa2ac04e17b9f72\",\"indexName\":\"feathers-casl\"}}},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false,\"additionalConfig\":{}}");</script>
215
216    
217  </body>
218</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.