{"id":13454985,"url":"https://github.com/stalniy/casl","last_synced_at":"2026-05-08T13:18:08.694Z","repository":{"id":38430754,"uuid":"97627474","full_name":"stalniy/casl","owner":"stalniy","description":"CASL is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access","archived":false,"fork":false,"pushed_at":"2025-05-10T18:18:12.000Z","size":21476,"stargazers_count":6358,"open_issues_count":32,"forks_count":282,"subscribers_count":40,"default_branch":"master","last_synced_at":"2025-05-11T18:36:54.159Z","etag":null,"topics":["acl","authorization","cancan","casl","isomorphic-javascript","permissions"],"latest_commit_sha":null,"homepage":"https://casl.js.org/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stalniy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":null,"patreon":"sstotskyi","open_collective":"casljs","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2017-07-18T17:49:47.000Z","updated_at":"2025-05-11T17:47:04.000Z","dependencies_parsed_at":"2025-04-30T13:43:09.653Z","dependency_job_id":"0c07da3f-bd10-4f23-a1fb-fa65da6863bf","html_url":"https://github.com/stalniy/casl","commit_stats":{"total_commits":1587,"total_committers":70,"mean_commits":22.67142857142857,"dds":"0.39823566477630745","last_synced_commit":"90ebc08e6fe7832126b909f0c6a2fd868d5fed19"},"previous_names":[],"tags_count":299,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalniy%2Fcasl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalniy%2Fcasl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalniy%2Fcasl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalniy%2Fcasl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stalniy","download_url":"https://codeload.github.com/stalniy/casl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253617994,"owners_count":21936899,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acl","authorization","cancan","casl","isomorphic-javascript","permissions"],"created_at":"2024-07-31T08:01:00.041Z","updated_at":"2026-04-20T06:12:14.095Z","avatar_url":"https://github.com/stalniy.png","language":"JavaScript","funding_links":["https://patreon.com/sstotskyi","https://opencollective.com/casljs","https://opencollective.com/casljs/contribute","https://opencollective.com/casljs/organization/0/website","https://opencollective.com/casljs/organization/1/website","https://opencollective.com/casljs/organization/2/website","https://opencollective.com/casljs/organization/3/website","https://opencollective.com/casljs/organization/4/website","https://opencollective.com/casljs/organization/5/website","https://opencollective.com/casljs/organization/6/website","https://opencollective.com/casljs/organization/7/website","https://opencollective.com/casljs/organization/8/website","https://opencollective.com/casljs/organization/9/website"],"categories":["TypeScript","Packages","JavaScript","Repository","包","目录","others","Authorization"],"sub_categories":["Authorization","授权","授权库"],"readme":"# CASL\n\n## Do you like this package?\n\n[Support Ukraine 🇺🇦](https://prytulafoundation.org/en/home/support_page)\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://stalniy.github.io/casl/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\u003cimg width=\"150\" src=\"docs-src/src/assets/shield.png\" alt=\"CASL logo\"\u003e\u003c/a\u003e\n\n[![Financial Contributors on Open Collective](https://opencollective.com/casljs/all/badge.svg?label=financial+contributors)](https://opencollective.com/casljs)\n![build](https://github.com/stalniy/casl/workflows/CI/badge.svg)\n[![CASL codecov](https://codecov.io/gh/stalniy/casl/branch/master/graph/badge.svg)](https://codecov.io/gh/stalniy/casl)\n[![Support](https://img.shields.io/badge/Support-github%20discussions-green?style=flat\u0026link=https://github.com/stalniy/casl/discussions)](https://github.com/stalniy/casl/discussions)\n\u003c!-- [![CASL Code Climate](https://codeclimate.com/github/stalniy/casl/badges/gpa.svg)](https://codeclimate.com/github/stalniy/casl) --\u003e\n\u003c/p\u003e\n\nCASL (pronounced /ˈkæsəl/, like **castle**) is an isomorphic authorization JavaScript library which restricts what resources a given user is allowed to access. It's designed to be incrementally adoptable and can easily scale between a simple claim based and fully featured subject and attribute based authorization. It makes it easy to manage and share permissions across UI components, API services, and database queries.\n\nHeavily inspired by [cancan](https://github.com/CanCanCommunity/cancancan).\n\n## Features\n\n* **Versatile**\\\n  An incrementally adoptable and can easily scale between a simple claim based and fully featured subject and attribute based authorization.\n* **Isomorphic**\\\n  Can be used on frontend and backend and complementary packages make integration with major Frontend Frameworks and Backend ORMs effortless\n* **TypeSafe**\\\n  Written in TypeScript, what makes your apps safer and developer experience more enjoyable\n* **Tree shakable**\\\n  The core is only 6KB mingzipped and can be even smaller!\n* **Declarative**\\\n  Thanks to declarative rules, you can serialize and share permissions between UI and API or microservices\n\n## Ecosystem\n\n| Project           | Status                               | Description | Supported environments |\n|-------------------|--------------------------------------|-------------|-------------------------|\n| [@casl/ability]   | [![@casl/ability-status]][@casl/ability-package]   | CASL's core package | Node.js 18+, browsers IE 11+ (uses `Map`/`Set`) |\n| [@casl/mongoose]  | [![@casl/mongoose-status]][@casl/mongoose-package] | integration with [Mongoose][mongoose] | Node.js 20 |\n| [@casl/prisma]  | [![@casl/prisma-status]][@casl/prisma-package] | integration with [Prisma][prisma] | Node.js 20+ |\n| [@casl/angular]   | [![@casl/angular-status]][@casl/angular-package]   | integration with  [Angular][angular] | Node.js 20+, browsers IE 11+ |\n| [@casl/react]     | [![@casl/react-status]][@casl/react-package]       | integration with  [React][react] | Node.js 20+, browsers IE 11+ |\n| [@casl/vue]       | [![@casl/vue-status]][@casl/vue-package]           | integration with  [Vue][vue] | Node.js 20+, browsers with `Symbol` support |\n| [@casl/aurelia]   | [![@casl/aurelia-status]][@casl/aurelia-package]   | integration with  [Aurelia][aurelia] | Node.js 20+, browsers IE 11+ (uses `WeakMap`) |\n\n[@casl/ability]: packages/casl-ability\n[@casl/mongoose]: packages/casl-mongoose\n[@casl/prisma]: packages/casl-prisma\n[@casl/angular]: packages/casl-angular\n[@casl/react]: packages/casl-react\n[@casl/vue]: packages/casl-vue\n[@casl/aurelia]: packages/casl-aurelia\n\n[@casl/ability-status]: https://img.shields.io/npm/v/@casl/ability.svg\n[@casl/mongoose-status]: https://img.shields.io/npm/v/@casl/mongoose.svg\n[@casl/prisma-status]: https://img.shields.io/npm/v/@casl/prisma.svg\n[@casl/angular-status]: https://img.shields.io/npm/v/@casl/angular.svg\n[@casl/react-status]: https://img.shields.io/npm/v/@casl/react.svg\n[@casl/vue-status]: https://img.shields.io/npm/v/@casl/vue.svg\n[@casl/aurelia-status]: https://img.shields.io/npm/v/@casl/aurelia.svg\n\n[@casl/ability-package]: https://www.npmjs.com/package/@casl/ability\n[@casl/mongoose-package]: https://www.npmjs.com/package/@casl/mongoose\n[@casl/prisma-package]: https://www.npmjs.com/package/@casl/prisma\n[@casl/angular-package]: https://www.npmjs.com/package/@casl/angular\n[@casl/react-package]: https://www.npmjs.com/package/@casl/react\n[@casl/vue-package]: https://www.npmjs.com/package/@casl/vue\n[@casl/aurelia-package]: https://www.npmjs.com/package/@casl/aurelia\n\n## Documentation\n\nA lot of detailed information about CASL, integrations and examples can be found in [documentation].\n\n## Have a question?\n\nAsk it in [support chat][support-chat] or on [stackoverflow](https://stackoverflow.com/questions/tagged/casl). Please don't ask questions in issues, the issue list of this repo is **exclusively** for bug reports and feature requests. Questions in the issue list may be closed immediately without answers.\n\n## CASL crash course\n\nCASL operates on the abilities level, that is what a user can actually do in the application. An ability itself depends on the 4 parameters (last 3 are optional):\n\n1. User Action\\\n   Describes what user can actually do in the app. User action is a word (usually a verb) which depends on the business logic (e.g., `prolong`, `read`). Very often it will be a list of words from CRUD - `create`, `read`, `update` and `delete`.\n2. Subject\\\n   The subject or subject type which you want to check user action on. Usually this is a business (or domain) entity name (e.g., `Subscription`, `BlogPost`, `User`).\n3. Conditions\\\n   An object or function which restricts user action only to matched subjects. This is useful when you need to give a permission on resources created by a user (e.g., to allow user to update and delete own `BlogPost`)\n4. Fields\\\n   Can be used to restrict user action only to matched subject's fields (e.g., to allow moderator to update `hidden` field of `BlogPost` but not update `description` or `title`)\n\nUsing CASL you can describe abilities using regular and inverted rules. Let's see how\n\n**Note:** all the examples below will be written in TypeScript but CASL can be used in similar way in ES6+ and Nodejs environments.\n\n### 1. Define Abilities\n\nLets define `Ability` for a blog website where visitors:\n* can read blog posts\n* can manage (i.e., do anything) own posts\n* cannot delete a post if it was created more than a day ago\n\n```ts\nimport { AbilityBuilder, createMongoAbility } from '@casl/ability'\nimport { User } from '../models'; // application specific interfaces\n\n/**\n * @param user contains details about logged in user: its id, name, email, etc\n */\nfunction defineAbilitiesFor(user: User) {\n  const { can, cannot, build } = new AbilityBuilder(createMongoAbility);\n\n  // can read blog posts\n  can('read', 'BlogPost');\n  // can manage (i.e., do anything) own posts\n  can('manage', 'BlogPost', { author: user.id });\n  // cannot delete a post if it was created more than a day ago\n  cannot('delete', 'BlogPost', {\n    createdAt: { $lt: Date.now() - 24 * 60 * 60 * 1000 }\n  });\n\n  return build();\n});\n```\n\nDo you see how easily business requirements were translated into CASL's rules?\n\n**Note**: you can use class instead of string as a subject type (e.g., `can('read', BlogPost)`)\n\nAnd yes, `Ability` class allow you to use some MongoDB operators to define conditions. Don't worry if you don't know MongoDB, it's not required and explained in details in [Defining Abilities][define-abilities]\n\n### 2. Check Abilities\n\nLater on you can check abilities by using `can` and `cannot` methods of `Ability` instance.\n\n```js\n// in the same file as above\nimport { ForbiddenError } from '@casl/ability';\n\nconst user = getLoggedInUser(); // app specific function\nconst ability = defineAbilitiesFor(user);\n\nclass BlogPost { // business entity\n  constructor(props) {\n    Object.assign(this, props);\n  }\n}\n\n// true if ability allows to read at least one Post\nability.can('read', 'BlogPost');\n// the same as\nability.can('read', BlogPost);\n\n// true, if user is the author of the blog post\nability.can('manage', new BlogPost({ author: user.id }));\n\n// true if there is no ability to read this particular blog post\nconst ONE_DAY = 24 * 60 * 60 * 1000;\nconst postCreatedNow = new BlogPost({ createdAt: new Date() });\nconst postCreatedAWeekAgo = new BlogPost({ createdAt: new Date(Date.now() - 7 * ONE_DAY) });\n\n// can delete if it's created less than a day ago\nability.can('delete', postCreatedNow); // true\nability.can('delete', postCreatedAWeekAgo); // false\n\n// you can even throw an error if there is a missed ability\nForbiddenError.from(ability).throwUnlessCan('delete', postCreatedAWeekAgo);\n```\n\nOf course, you are not restricted to use only class instances in order to check permissions on objects. See [Introduction][intro] for the detailed explanation.\n\n### 3. Database integration\n\nCASL has a complementary package [@casl/mongoose] which provides easy integration with MongoDB and [mongoose].\n\n```ts\nimport { accessibleRecordsPlugin } from '@casl/mongoose';\nimport mongoose from 'mongoose';\n\nmongoose.plugin(accessibleRecordsPlugin);\n\nconst user = getUserLoggedInUser(); // app specific function\n\nconst ability = defineAbilitiesFor(user);\nconst BlogPost = mongoose.model('BlogPost', mongoose.Schema({\n  title: String,\n  author: mongoose.Types.ObjectId,\n  content: String,\n  createdAt: Date,\n  hidden: { type: Boolean, default: false }\n}))\n\n// returns mongoose Query, so you can chain it with other conditions\nconst posts = await BlogPost.accessibleBy(ability).where({ hidden: false });\n\n// you can also call it on existing query to enforce permissions\nconst hiddenPosts = await BlogPost.find({ hidden: true }).accessibleBy(ability);\n\n// you can even pass the action as a 2nd parameter. By default action is \"read\"\nconst updatablePosts = await BlogPost.accessibleBy(ability, 'update');\n```\n\nSee [Database integration][database-integration] for details.\n\n### 4. Advanced usage\n\n**CASL is incrementally adoptable**, that means you can start your project with simple claim (or action) based authorization and evolve it later, when your app functionality evolves.\n\n**CASL is composable**, that means you can implement alternative conditions matching (e.g., based on [joi], [ajv] or pure functions) and field matching (e.g., to support alternative syntax in fields like `addresses.*.street` or `addresses[0].street`) logic.\n\nSee [Advanced usage][advanced-usage] for details.\n\n[joi]: https://www.npmjs.com/package/@hapi/joi\n[ajv]: https://www.npmjs.com/package/ajv\n\n### 5. Examples\n\nLooking for examples? Check [CASL examples](https://github.com/stalniy/casl-examples) repository.\n\n## Want to help?\n\nWant to file a bug, contribute some code, or improve documentation? Excellent! Read up on guidelines for [contributing].\n\nIf you'd like to help us sustain our community and project, consider [to become a financial contributor on Open Collective](https://opencollective.com/casljs/contribute)\n\n## Contributors\n\n### Code Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n\u003ca href=\"https://github.com/stalniy/casl/graphs/contributors\"\u003e\u003cimg src=\"https://opencollective.com/casljs/contributors.svg?width=890\u0026button=false\" /\u003e\u003c/a\u003e\n\n### Financial Contributors\n\nBecome a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/casljs/contribute)]\n\n#### Individuals\n\n\u003ca href=\"https://opencollective.com/casljs\"\u003e\u003cimg src=\"https://opencollective.com/casljs/individuals.svg?width=890\"\u003e\u003c/a\u003e\n\n#### Organizations\n\nSupport this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/casljs/contribute)]\n\n\u003ca href=\"https://opencollective.com/casljs/organization/0/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/0/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/1/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/1/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/2/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/2/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/3/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/3/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/4/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/4/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/5/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/5/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/6/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/6/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/7/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/7/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/8/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/8/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/casljs/organization/9/website\"\u003e\u003cimg src=\"https://opencollective.com/casljs/organization/9/avatar.svg\"\u003e\u003c/a\u003e\n\n## License\n\n[MIT License](http://www.opensource.org/licenses/MIT)\n\nCopyright (c) 2017-present, Sergii Stotskyi\n\n[contributing]: https://github.com/stalniy/casl/blob/master/CONTRIBUTING.md\n[define-abilities]: https://stalniy.github.io/casl/en/guide/define-rules\n[intro]: https://stalniy.github.io/casl/en/guide/intro\n[database-integration]: https://stalniy.github.io/casl/en/package/casl-mongoose\n[documentation]: https://stalniy.github.io/casl/\n[advanced-usage]: https://stalniy.github.io/casl/en/advanced/customize-ability\n\n[mongoose]: http://mongoosejs.com/\n[vue]: https://vuejs.org\n[angular]: https://angular.io/\n[react]: https://reactjs.org/\n[aurelia]: http://aurelia.io\n[prisma]: https://www.prisma.io/\n[support-chat]: https://github.com/stalniy/casl/discussions\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstalniy%2Fcasl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstalniy%2Fcasl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstalniy%2Fcasl/lists"}