Manage user access to your PayloadCMS admin panel by adding, editing, and removing user accounts. This guide covers user management for the built-in Users collection.
Prerequisites
- PayloadCMS installed and configured
- Admin access to Payload Admin Panel
- Understanding of your Payload config (especially auth settings)
Adding Users via Admin Panel
Step 1: Access Users Collection
- Log in to Payload Admin Panel (usually
/admin) - Navigate to Users in the sidebar
- Click Create New
Step 2: Fill in User Details
Required Fields:
- Email: User's email address (must be unique)
- Password: Secure password
- Confirm Password: Password confirmation
Optional Fields (depends on your config):
- Name/First Name/Last Name
- Role (if roles are configured)
- Avatar/Profile Picture
- Custom fields you've added to Users collection
Step 3: Set User Role
If you have roles configured:
// Example: Your payload.config.ts might have
const Users: CollectionConfig = {
slug: 'users',
auth: true,
fields: [
{
name: 'role',
type: 'select',
options: [
{ label: 'Admin', value: 'admin' },
{ label: 'Editor', value: 'editor' },
{ label: 'Author', value: 'author' },
],
required: true,
defaultValue: 'author',
},
],
};
Select appropriate role from dropdown.
Step 4: Save User
Click Save to create the user account.
Result: User receives email with login credentials (if email is configured).
Adding Users Programmatically
Via Payload Local API
File: scripts/create-user.ts
import payload from 'payload';
async function createUser() {
await payload.init({
secret: process.env.PAYLOAD_SECRET,
mongoURL: process.env.MONGODB_URI,
local: true,
});
const newUser = await payload.create({
collection: 'users',
data: {
email: 'newuser@example.com',
password: 'SecurePassword123!',
role: 'editor',
name: 'John Doe',
},
});
console.log('User created:', newUser.id);
process.exit(0);
}
createUser();
Run script:
ts-node scripts/create-user.ts
Via REST API
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-d '{
"email": "newuser@example.com",
"password": "SecurePassword123!",
"role": "editor"
}'
Note: Requires authentication. Get token by logging in first.
Editing Existing Users
Via Admin Panel
- Go to Users collection
- Click on user to edit
- Modify fields as needed
- Click Save
Update User Password
As admin (in admin panel):
- Navigate to user
- Scroll to Password field
- Enter new password
- Confirm password
- Save
User self-service (if enabled):
- Users can update their own password in their profile
- Accessible via user menu (top right) > Account
Removing Users
Via Admin Panel
- Navigate to Users
- Find user to delete
- Click user to open
- Click Delete (usually bottom of form or in menu)
- Confirm deletion
Warning: Deleting a user is permanent and cannot be undone.
Deactivate Instead of Delete
Better practice: Add an "active" field instead of deleting:
// collections/Users.ts
{
name: 'active',
type: 'checkbox',
defaultValue: true,
admin: {
description: 'Uncheck to deactivate user',
},
}
Then filter login by active status in access control.
Bulk User Management
Import Multiple Users
File: scripts/bulk-import-users.ts
import payload from 'payload';
import fs from 'fs';
import csv from 'csv-parser';
async function importUsers() {
await payload.init({
secret: process.env.PAYLOAD_SECRET,
mongoURL: process.env.MONGODB_URI,
local: true,
});
const users = [];
// Read from CSV
fs.createReadStream('users.csv')
.pipe(csv())
.on('data', (row) => {
users.push({
email: row.email,
password: row.password,
name: row.name,
role: row.role || 'author',
});
})
.on('end', async () => {
for (const userData of users) {
try {
await payload.create({
collection: 'users',
data: userData,
});
console.log(`Created: ${userData.email}`);
} catch (error) {
console.error(`Failed: ${userData.email}`, error);
}
}
process.exit(0);
});
}
importUsers();
CSV format (users.csv):
email,password,name,role
user1@example.com,Password123,John Doe,editor
user2@example.com,Password456,Jane Smith,author
User Invitations
Send Email Invitations
If you have email configured:
File: collections/Invitations.ts
import { CollectionConfig } from 'payload/types';
const Invitations: CollectionConfig = {
slug: 'invitations',
fields: [
{
name: 'email',
type: 'email',
required: true,
unique: true,
},
{
name: 'role',
type: 'select',
options: ['admin', 'editor', 'author'],
required: true,
},
{
name: 'token',
type: 'text',
admin: {
readOnly: true,
},
},
{
name: 'status',
type: 'select',
options: ['pending', 'accepted', 'expired'],
defaultValue: 'pending',
},
],
hooks: {
beforeChange: [
async ({ operation, data }) => {
if (operation === 'create') {
// Generate unique token
data.token = generateToken();
// Send invitation email
await sendInvitationEmail(data.email, data.token);
}
return data;
},
],
},
};
export default Invitations;
Managing Your Own Account
Change Your Password
- Click user menu (top right)
- Select Account
- Update password fields
- Save
Update Profile
- Go to Account
- Modify name, email, or other profile fields
- Save changes
User Access Logs
Track User Activity
Add activity logging:
File: collections/Users.ts
{
name: 'lastLogin',
type: 'date',
admin: {
readOnly: true,
},
}
Update on login:
// In auth hooks
afterLogin: [
async ({ req, user }) => {
await req.payload.update({
collection: 'users',
id: user.id,
data: {
lastLogin: new Date(),
},
});
},
],
Security Best Practices
Password Requirements
Configure strong passwords:
File: collections/Users.ts
const Users: CollectionConfig = {
slug: 'users',
auth: {
verify: true, // Email verification
maxLoginAttempts: 5,
lockTime: 600000, // 10 minutes
tokenExpiration: 7200, // 2 hours
depth: 0,
},
fields: [
{
name: 'password',
type: 'text',
required: true,
minLength: 8,
},
],
};
Remove Inactive Users
Regular cleanup of inactive accounts:
// scripts/cleanup-users.ts
async function removeInactiveUsers() {
const sixMonthsAgo = new Date();
sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
const inactiveUsers = await payload.find({
collection: 'users',
where: {
and: [
{
lastLogin: {
less_than: sixMonthsAgo,
},
},
{
role: {
not_equals: 'admin',
},
},
],
},
});
for (const user of inactiveUsers.docs) {
await payload.delete({
collection: 'users',
id: user.id,
});
console.log(`Removed inactive user: ${user.email}`);
}
}
Troubleshooting
Issue: Can't Create User
Error: "Email already exists"
Solution: Email must be unique. Check if user already exists.
Issue: Password Reset Not Working
Solution:
- Verify email configuration
- Check email is being sent (check logs)
- Ensure SMTP credentials are correct
Issue: User Can't Log In
Check:
- Account is active
- Password is correct
- Account not locked (after failed login attempts)
- Email verified (if verification enabled)