Complete guide to configuring user groups, assigning permissions, and implementing role-based access control (RBAC) in Craft CMS.
Understanding User Groups
User groups in Craft CMS organize users and define their permissions:
- Permission Assignment - Assign permissions to groups, not individual users
- Multiple Groups - Users can belong to multiple groups
- Permission Inheritance - Users inherit all permissions from all their groups
- Custom Fields - Each group can have unique custom fields
Creating User Groups
Via Control Panel
- Navigate to Settings → Users → User Groups
- Click + New user group
- Configure the group:
- Name - Display name for the group
- Handle - System handle (used in code)
- Description - Optional description
- Permissions - Select group permissions
Common User Group Setup
Structure:
├── Administrators (Full access)
├── Editors (Content + limited settings)
├── Authors (Own content only)
├── Members (Front-end only, no CP access)
└── Guests (Not logged in)
Permission Types
System Permissions
Control Panel Access
Access the Control Panel
├── Required for any CP access
└── Without this, users are front-end only
Access the Control Panel when the system is offline
├── Allow access during maintenance
└── Typically for administrators only
Perform Craft CMS and plugin updates
├── Install/update Craft and plugins
└── Critical system permission
User Permissions
Edit users
├── Can create/edit user accounts
└── Can assign to groups they belong to
Administrate users
├── Full user management
├── Can assign users to any group
└── Can change admin status
Register users
├── Can create new user accounts
└── Useful for customer service roles
Assign user permissions
├── Can modify individual user permissions
└── Should be limited to administrators
Assign users to user groups
├── Can add/remove users from groups
└── Limited to groups they belong to
Delete users
└── Permanent user removal
Content Permissions
Entry Permissions (Per Section)
View entries
├── Can see entries in this section
└── Base permission for all entry work
Create entries
├── Can create new entries
└── May be limited to drafts
Save entries
├── Can save changes to entries
└── Includes own and others' entries
Delete entries
├── Can permanently delete entries
└── Separate from "Delete own entries"
Publish entries
├── Can change entry status to Live
└── May require approval workflow
Edit other authors' entries
├── Can edit entries created by others
└── Important for editorial workflow
Publish other authors' entries
├── Can publish entries created by others
└── Typically for editors/reviewers
Delete other authors' entries
└── Can delete entries created by others
Asset Permissions (Per Volume)
View assets
├── Can see assets in this volume
└── Required for all asset operations
Save assets
├── Can upload new assets
└── Can edit existing assets
Delete assets
└── Can permanently delete assets
Replace files
├── Can replace asset files
└── Maintains asset ID and references
Edit images
├── Can use image editor
└── Crop, rotate, adjust images
Create subfolders
└── Can organize assets into folders
Category Permissions
View categories
Save categories
Delete categories
Configuring Group Permissions
Example: Editors Group
Configure a typical editors group with appropriate permissions:
Editors Group Configuration:
Control Panel:
☑ Access the Control Panel
☐ Access CP when offline
☐ Perform updates
Users:
☑ Edit users (own group only)
☐ Administrate users
☐ Delete users
Entries - Blog Section:
☑ View entries
☑ Create entries
☑ Save entries
☑ Delete entries (own only)
☑ Publish entries (own only)
☑ Edit other authors' entries
☑ Publish other authors' entries
☐ Delete other authors' entries
Assets - Documents Volume:
☑ View assets
☑ Save assets
☐ Delete assets
☑ Replace files
☑ Edit images
☑ Create subfolders
Settings:
☐ Edit site settings
☐ Edit plugin settings
Example: Authors Group
Configure a writers/authors group:
Authors Group Configuration:
Control Panel:
☑ Access the Control Panel
☐ Access CP when offline
☐ Perform updates
Users:
☐ Edit users
☐ Administrate users
Entries - Blog Section:
☑ View entries
☑ Create entries
☑ Save entries
☑ Delete entries (own only)
☐ Publish entries (requires approval)
☐ Edit other authors' entries
☐ Publish other authors' entries
Assets - Images Volume:
☑ View assets
☑ Save assets
☐ Delete assets
☑ Replace files (own only)
☑ Edit images
☐ Create subfolders
Example: Members Group (Front-End Only)
Configure a members group for front-end users:
Members Group Configuration:
Control Panel:
☐ Access the Control Panel
Users:
☐ All user permissions disabled
Entries:
☐ All entry permissions disabled
(Front-end users don't access CP)
Custom Permissions:
(Via custom plugin or module)
☑ Access member area
☑ Edit own profile
☑ Submit comments
☑ View premium content
Section-Specific Permissions
Per-Section Configuration
Different sections can have different permission requirements:
{# Check section-specific permissions #}
{% if currentUser and currentUser.can('editEntries:blog') %}
<a href="{{ cpUrl('entries/blog/new') }}">Create Blog Post</a>
{% endif %}
{% if currentUser and currentUser.can('editEntries:news') %}
<a href="{{ cpUrl('entries/news/new') }}">Create News Article</a>
{% endif %}
{% if currentUser and currentUser.can('publishEntries:blog') %}
<button>Publish</button>
{% else %}
<button>Save Draft</button>
{% endif %}
Volume-Specific Permissions
Control asset access per volume:
{# Check volume-specific permissions #}
{% if currentUser and currentUser.can('saveAssetInVolume:documents') %}
<input type="file" name="document">
{% endif %}
{% if currentUser and currentUser.can('deleteAssetInVolume:images') %}
<button>Delete Image</button>
{% endif %}
Checking Permissions in Templates
Basic Permission Checks
{# Check if user has specific permission #}
{% if currentUser and currentUser.can('accessCp') %}
<a href="{{ cpUrl() }}">Control Panel</a>
{% endif %}
{# Check multiple permissions #}
{% if currentUser and
currentUser.can('editEntries:blog') and
currentUser.can('publishEntries:blog') %}
<p>Full blog editing access</p>
{% endif %}
{# Check if user is in group #}
{% if currentUser and currentUser.isInGroup('editors') %}
<div class="editor-tools">
{# Editor-specific tools #}
</div>
{% endif %}
{# Check multiple groups #}
{% if currentUser and
(currentUser.isInGroup('editors') or
currentUser.isInGroup('administrators')) %}
<p>Administrative access</p>
{% endif %}
Advanced Permission Logic
{# Check if user can edit a specific entry #}
{% set entry = craft.entries().id(123).one() %}
{% if currentUser %}
{% set canEdit = false %}
{# Can edit own entries #}
{% if entry.authorId == currentUser.id and
currentUser.can('editEntries:' ~ entry.section.handle) %}
{% set canEdit = true %}
{% endif %}
{# Can edit others' entries #}
{% if currentUser.can('editPeerEntries:' ~ entry.section.handle) %}
{% set canEdit = true %}
{% endif %}
{# Administrators can edit anything #}
{% if currentUser.admin %}
{% set canEdit = true %}
{% endif %}
{% if canEdit %}
<a href="{{ entry.cpEditUrl }}">Edit Entry</a>
{% endif %}
{% endif %}
Permission Hierarchies
Permission Dependencies
Some permissions require others:
To delete entries:
├── Must have "View entries"
└── Must have "Delete entries"
To publish entries:
├── Must have "View entries"
├── Must have "Save entries"
└── Must have "Publish entries"
To edit other authors' entries:
├── Must have "View entries"
├── Must have "Save entries"
└── Must have "Edit other authors' entries"
Admin Override
Administrators bypass all permission checks:
{# Admin users have all permissions #}
{% if currentUser and currentUser.admin %}
<p>Administrator - Full Access</p>
{% else %}
{# Check specific permissions #}
{% endif %}
Custom Permission Implementation
Via Custom Module
Create custom permissions for specific features:
<?php
// modules/userpermissions/Module.php
namespace modules\userpermissions;
use Craft;
use craft\events\RegisterUserPermissionsEvent;
use craft\services\UserPermissions;
use yii\base\Event;
use yii\base\Module as BaseModule;
class Module extends BaseModule
{
public function init()
{
parent::init();
Event::on(
UserPermissions::class,
UserPermissions::EVENT_REGISTER_PERMISSIONS,
function(RegisterUserPermissionsEvent $event) {
$event->permissions[] = [
'heading' => 'Custom Features',
'permissions' => [
'accessMemberArea' => [
'label' => 'Access member area',
],
'viewPremiumContent' => [
'label' => 'View premium content',
],
'submitComments' => [
'label' => 'Submit comments',
],
'moderateComments' => [
'label' => 'Moderate comments',
],
],
];
}
);
}
}
Use custom permissions in templates:
{% if currentUser and currentUser.can('accessMemberArea') %}
{{ include('_members/dashboard') }}
{% endif %}
{% if currentUser and currentUser.can('viewPremiumContent') %}
{{ entry.premiumContent }}
{% endif %}
Multi-Site Permissions
Per-Site User Access
Configure which sites users can access:
// Via Control Panel:
// User → Edit → Sites
// Select which sites this user can access
// Or programmatically:
$user = craft\elements\User::find()->id(123)->one();
$user->setSiteIds([1, 3, 5]); // Can access sites 1, 3, and 5
Craft::$app->elements->saveElement($user);
Check Site Access in Templates
{# Check if user can access current site #}
{% if currentUser and currentUser.canAccessSite(currentSite) %}
<p>Access granted for {{ currentSite.name }}</p>
{% else %}
<p>You don't have access to this site</p>
{% endif %}
{# List sites user can access #}
{% if currentUser %}
<ul>
{% for site in craft.app.sites.allSites %}
{% if currentUser.canAccessSite(site) %}
<li>{{ site.name }}</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
Best Practices
1. Principle of Least Privilege
Grant only the minimum permissions required:
BAD: Give everyone "Administrators" group
GOOD: Create specific groups for each role
2. Use Groups, Not Individual Permissions
Assign permissions to groups, not individual users:
BAD: Manually set permissions for each user
GOOD: Create groups and assign users to groups
3. Document Permission Structure
Maintain documentation of your permission model:
# Permission Structure
## Administrators
- Full system access
- Can manage users and settings
- Can publish to production
## Editors
- Can create and edit all content
- Can publish content
- Cannot access system settings
## Authors
- Can create and edit own content
- Cannot publish (requires approval)
- Limited asset access
4. Regular Permission Audits
Review user permissions regularly:
{# Generate permission audit report #}
{% set users = craft.users().all() %}
<table>
<thead>
<tr>
<th>User</th>
<th>Groups</th>
<th>Last Login</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.fullName }}</td>
<td>
{% for group in user.groups %}
{{ group.name }}{{ not loop.last ? ', ' }}
{% endfor %}
</td>
<td>{{ user.lastLoginDate|date('Y-m-d H:i') }}</td>
<td>{{ user.status }}</td>
</tr>
{% endfor %}
</tbody>
</table>
5. Test Permission Changes
Always test permission changes before deploying:
- Create test user in each group
- Verify they can access what they should
- Verify they cannot access what they shouldn't
- Test edge cases and workflows
Permission Reference
Complete Permission List
// Access permissions
'accessCp' => Access the Control Panel
'accessCpWhenSystemIsOff' => Access CP when offline
'performUpdates' => Perform Craft and plugin updates
// User permissions
'editUsers' => Edit users
'registerUsers' => Register users
'assignUserPermissions' => Assign user permissions
'assignUserGroups' => Assign users to groups
'administrateUsers' => Administrate users
'deleteUsers' => Delete users
// Entry permissions (per section)
'viewEntries:{sectionHandle}' => View entries
'createEntries:{sectionHandle}' => Create entries
'saveEntries:{sectionHandle}' => Save entries
'deleteEntries:{sectionHandle}' => Delete entries
'publishEntries:{sectionHandle}' => Publish entries
'editPeerEntries:{sectionHandle}' => Edit other authors' entries
'publishPeerEntries:{sectionHandle}' => Publish other authors' entries
'deletePeerEntries:{sectionHandle}' => Delete other authors' entries
// Asset permissions (per volume)
'viewAssets:{volumeHandle}' => View assets
'saveAssetInVolume:{volumeHandle}' => Save assets
'deleteAssetInVolume:{volumeHandle}' => Delete assets
'replaceFilesInVolume:{volumeHandle}' => Replace files
'editImagesInVolume:{volumeHandle}' => Edit images
'createFoldersInVolume:{volumeHandle}' => Create folders
// Category permissions
'viewCategories:{groupHandle}' => View categories
'saveCategories:{groupHandle}' => Save categories
'deleteCategories:{groupHandle}' => Delete categories
// Global permissions
'editGlobalSet:{handle}' => Edit global set
// Utility permissions
'utility:{utilityHandle}' => Access utility
Next Steps
- Adding/Removing Users - Manage user accounts
- User Management Overview - User management fundamentals