Permissions
Permissions
This document explains the comprehensive permission system implemented in Nuxt Auto Admin.
Configuration
Add permission configuration to your nuxt.config.ts:
export default defineNuxtConfig({
autoAdmin: {
permissions: {
// How to handle buttons when user lacks permission
// 'disable' = show buttons but disable them (default)
// 'hide' = completely hide buttons
unauthorizedButtons: 'disable',
// How to handle sidebar items when user lacks permission
// 'hide' = completely hide items from sidebar (default)
// 'disable' = show items but in disabled state (grayed out, not clickable)
unauthorizedSidebarItems: 'hide'
}
}
})
Features
1. Button Behavior
Buttons respect the unauthorizedButtons configuration:
When set to 'disable' (default):
- Buttons are shown but disabled
- Forms show with all fields disabled
- User sees an orange warning banner indicating limited access
- Better UX - user can see what they could do with proper permissions
When set to 'hide':
- Buttons are completely hidden from UI
- Forms show a red permission denied message
- Stricter access control
Affected buttons:
- "Create New" button on list pages
- "Edit" and "Delete" buttons on detail pages
- "Save" button on edit/create forms
- Action buttons in table context menus (always shown but disabled)
2. Sidebar Menu Items
Sidebar items respect the unauthorizedSidebarItems configuration:
When set to 'hide' (default):
- Resources without any permissions are removed from sidebar
- Cleaner UI showing only accessible resources
When set to 'disable':
- Resources without permissions are shown but grayed out
- Not clickable (rendered as
<div>instead of<NuxtLink>) - User can see what resources exist but can't access them
3. Table Context Menu
The dropdown menu in table rows now shows all actions but disables them based on permissions:
// Items are always shown in menu
items = [
{ label: 'View', icon: 'i-heroicons-eye', onSelect: ... },
{ label: 'Edit', icon: 'i-heroicons-pencil', disabled: !canUpdate, onSelect: ... },
{ label: 'Delete', icon: 'i-heroicons-trash', disabled: !canDelete, onSelect: ... }
]
4. Direct URL Access Protection
A global middleware (permissions.global.ts) intercepts all admin routes and checks permissions:
- Checks if user has any permission for the resource
- Returns 403 Forbidden if no permission
- Shows nice error page with "Go Back" and "Go to Dashboard" buttons
- Works for both resource routes and custom pages
5. Custom Pages Permissions
Custom pages can define permissions in two ways:
Using permission strings:
customPages: [
{
name: 'settings',
label: 'Settings',
path: 'settings',
icon: 'i-heroicons-cog-6-tooth',
// Single permission
permissions: 'admin'
// OR multiple permissions (user needs ALL)
// permissions: ['admin', 'settings.manage']
}
]
Using canAccess function:
customPages: [
{
name: 'analytics',
label: 'Analytics',
path: 'analytics',
icon: 'i-heroicons-chart-bar',
canAccess: async (user) => {
// Custom logic
return user?.role === 'admin' || user?.permissions?.includes('analytics.view')
}
}
]
6. Form Disabled State
When a user lacks update permission but unauthorizedButtons is set to 'disable':
- All form fields are disabled via cascading
disabledprop - Save button is disabled
- Reset button is disabled
- M2M relation cards are disabled (select + save buttons)
- Orange warning banner shows "Limited Access" message
7. Permission Denied Pages
Users see appropriate error messages when accessing unauthorized pages:
403 Forbidden Error:
- Shows permission denied icon
- Clear error message
- "Go Back" and "Go to Dashboard" buttons
- Consistent styling with the rest of the admin panel
Components Updated
Pages
admin/[resource]/index.vue- List page with Create buttonadmin/[resource]/[id].vue- Detail page with Edit/Delete buttons and read permission checkadmin/[resource]/[id]/edit.vue- Edit page with disabled form optionadmin/[resource]/new.vue- Create page with disabled form optionadmin/error.vue- Error page for permission denied and other errors
Components
ResourceTable.vue- Context menu actions always shown but disabledResourceForm.vue- AcceptsdisabledpropAutoForm.vue- Cascadesdisabledto all fields and buttonsAutoField.vue- Passesdisabledto widgetsM2MRelationCard.vue- Supports disabled stateResourceNavLink.vue- Shows resource links based on permissionsCustomPageNavLink.vue- Shows custom page links based on permissionsAdminSidebar.vue- Filters/disables items based on configPermissionDeniedPage.vue- Reusable permission denied component
New Files
composables/useAdminConfig.ts- Access admin configurationmiddleware/permissions.global.ts- Global route guardcomponents/PermissionDeniedPage.vue- Permission denied UIpages/admin/error.vue- Error page handler
Permission Checks
The system uses the existing useAdminPermissions composable which provides:
const {
canCreate,
canRead,
canUpdate,
canDelete,
hasAnyPermission,
isLoading,
getPermissionDeniedMessage
} = useAdminPermissions(resourceName)
Examples
Example 1: Strict Access Control
autoAdmin: {
permissions: {
unauthorizedButtons: 'hide',
unauthorizedSidebarItems: 'hide'
}
}
Result:
- Users only see what they can access
- No disabled buttons or grayed out items
- Cleaner, simpler UI
- Users might not know what they're missing
Example 2: Transparent Access Control
autoAdmin: {
permissions: {
unauthorizedButtons: 'disable',
unauthorizedSidebarItems: 'disable'
}
}
Result:
- Users see all features but can't use unauthorized ones
- Clear indication of what exists but is restricted
- Better for discovering what permissions they might need
- More helpful warning messages
Example 3: Balanced Approach (Default)
autoAdmin: {
permissions: {
unauthorizedButtons: 'disable',
unauthorizedSidebarItems: 'hide'
}
}
Result:
- Sidebar is clean (only shows accessible resources)
- Within accessible resources, users see disabled buttons
- Good balance between discoverability and simplicity
Best Practices
- Choose based on your use case:
- Hide buttons/items for external users or strict security
- Disable buttons/items for internal users who might request access
- Custom pages should always use
canAccessfor complex permission logic - The middleware protects all routes - even if UI shows something, the middleware will block unauthorized access
- Test both configurations to see which provides better UX for your users
- Permission denied messages are customizable via the
getPermissionDeniedMessagefunction
Migration
If you're upgrading from a previous version:
- Add the
permissionsconfig to yournuxt.config.ts(optional, has defaults) - Existing functionality works as before
- The default behavior (
unauthorizedButtons: 'disable') is more permissive than the old hide-only behavior - If you want the old behavior, set
unauthorizedButtons: 'hide'
Form Fields & Widgets
Customize create and edit forms with various widget types.
Custom Pages
Add custom pages to your admin panel for features beyond standard CRUD operations.