nuxt-authorizer
v0.0.3
Published
A lightweight and flexible authorization module for Nuxt App
Downloads
4
Maintainers
Readme
Nuxt Authorizer
A lightweight and flexible authorization module for Nuxt App.
Features
- [x] Declarative abilities - Define permission rules using a clean, composable API.
- [x] Full-stack authorization - Works in both client and server through unified utilities.
- [x] Component-level access control -
<Can>and<Cannot>components included. - [x] Type-safe rules — Strong TypeScript support for better DX.
- [x] Nested and array-based abilities - Model complex permission logic easily.
- [x] Customizable callbacks & error handling - Override messages, status codes, and execution logic.
Quick Setup
Install the module to your Nuxt application with one command:
npx nuxi module add nuxt-authorizerThat's it! You can now use Nuxt Authorizer in your Nuxt app ✨
Documentation
Quick Start
Define ability
const editPost = defineAbility((user: User, post: Post) => user.id === post.authorId)Usage (Client or Server)
const allowed = await allows(editPost, user, post)
const denied = await denies(editPost, user, post)Usage with component
<template>
<div>
<Can :ability="editPost" :args="[user, post]">
<p>Authorized</>
</Can>
<Cannot :ability="editPost" :args=[user, post]>
<p>Unauthorized</>
</Cannot>
</div>
</template>Usage with composables
<script lang="ts" setup>
const { authorized, execute } = useAbility(editPost)
</script>
<template>
<div>
<button @click="execute(user, post)">Edit</button>
<div v-if="authorized">
Authorized
</div>
</div>
</template>Throw error if Unauthorized (Server)
await authorize(editPost, user, post)
Ability
Transform any function that has a boolean return, rule, or array rules into an ability.
Nested Ability
define ability
[!NOTE] You can define abilities wherever you want, but if static is recommended in the
/shared/utilsfolder (Nuxt v4).
const ability = defineAbility((user: User) => {
post: (post: Post) => ({
edit: () => user.id === post.authorId,
delete: () => user.role === 'admin' || user.id === post.authorId
}),
comment: () => ({
create: () => !!user,
edit: (comment: Comment) => user.id === comment.authorId
})
})
Usage
// Server or Client
const allowed = await allows(ability, user, 'post', 'edit')
const denied = await denies(ability, user, 'post', 'edit')
// Server
await authorize(ability, user, 'post', 'edit')
// Composables
const {authorized, execute} = useAbility(ability)
execute(user, 'post', 'edit')Usage with component
<template>
<div>
<Can :ability="ability" :args="[user, 'post', 'edit']">
<div> Authorized </>
</Can>
<Cannot :ability="ability" :args="[user, 'post', 'edit']">
<div> Authorized </>
</Cannot>
</div>
</template>Array Abilities
Unlike nested abilities, Array abilities evaluate all rules. If any rule returns false, the result is false.
// define ability/rule
const editPost = defineAbility((user: User, post: Post) => user.id === post.authorId)
const arrayAbilities = defineAbility([
editPost,
() => true,
async(user: User, post: Post) => Promise.resolve(user.id === post.authorId)
] as const /* for better type */)
// usage
const passed = await allows(arrayAbilities, [user, post /* ARGS_RULE_1 */], [/* ARGS_RULE_2 */], [/* ARGS_RULE_3 */])
// Composables
const {authorized, execute} = useAbility(arrayAbilities)
execute([user, post /* ARGS_RULE_1 */], [/* ARGS_RULE_2 */], [/* ARGS_RULE_3 */])Use with component
<template>
<div>
<Can :ability="arrayAbilities" :args="[]">
</div>
</template>Nested Array Abilities
const canAccess = defineAbility([
(user: User) => [
async() => await isVerified(user.id),
(role: string) => user.role === role,
]
])Dynamic rule
const rule = await getRuleByUser(userId)
const ability = defineAbility(rule)
// Usage
const allowed = await ability(/* PARAMETERS /*)or you can use useAbility, composables accept functions (rules) or abilities
Options
Set Callback in ability
m
const ability = defineAbility(() => true, {
onAuthorized: () => {
// Your implementations
},
onUnauthorized: (message, statusCode) => {
// Your implementations
}
})Custom error status code and message
const ability = defineAbility(() => true, {
statusCode: 401,
message: 'Unauthorized'
})Set Callback in composables
<script lang="ts" setup>
const { authorized } = useAbility(ability, {
onAuthorized: () => {
// Your implementations
},
onUnauthorized: (message, statusCode) => {
// Your implementations
}
})
</script>Custom executor
const ability = defineAbility(() => true, {
executor: (rule, args) => {
return true
}
})Contribution
# Install dependencies
pnpm install
# Generate type stubs
pnpm run dev:prepare
# Develop with the playground
pnpm run dev
# Build the playground
pnpm run dev:build
# Run ESLint
pnpm run lint
# Run Vitest
pnpm run test
pnpm run test:watch
# Release new version
pnpm run release