nextjs-cms

Admins & Permissions

Create admin accounts and decide, section by section, what each admin can see, create, update, and delete.

Admins are the people who sign in to the CMS. They're managed on the built-in Admins page, not in section files.

The Master admin

nextjs-cms setup creates an account named Master with access to everything. It:

  • Can't be deleted.
  • Is granted every new section automatically each time you run update-sections.
  • Can have its password reset from the command line:
Terminal
pnpm nextjs-cms --dev set-master-admin

If the Master admin ever loses access to some sections (for example after restoring an old database), rebuild its permissions:

Terminal
pnpm nextjs-cms --dev fix-master-admin

Creating admins

On the Admins page, an admin with access to it can create accounts with a username, a password, and a list of privileges. Each admin can then manage their own account (password and preferences such as the interface language) in Settings.

How permissions work

A privilege grants one admin access to one section, with a set of operations:

LetterOperationAllows
CCreateThe "New" button and creating items
UUpdateEditing existing items (and simple sections)
DDeleteDeleting items and translations

Operations combine: C, U, D, CU, CD, UD, or CUD. Having any privilege on a section also lets the admin see it in the sidebar and browse its items. Without a privilege, the section doesn't exist for that admin: it's hidden from navigation and its URLs and API calls are rejected.

Privileges are stored in the admin_privileges table:

admin_privileges
admin_id │ section_name │ operations
─────────┼──────────────┼───────────
 a1b2    │ posts        │ CUD
 a1b2    │ categories   │ U
 c3d4    │ posts        │ CU

What can be granted

Besides your sections, the privileges list includes:

NameGrants
adminsThe Admins page: creating, editing, and removing other admins. Give it only to people you'd trust with full control.
logThe activity log.
Each pluginAccess to the plugin's pages, listed by plugin title.

Typical setups

RolePrivileges
OwnerMaster, or every section with CUD plus admins
EditorContent sections with CUD
Authorposts with CU (can't delete), categories with no access
TranslatorContent sections with U only
ReviewerContent sections with U, log

Enforcing extra rules

Privileges are per section and per operation. For rules about the data ("featured posts can't be deleted"), use a before* hook. Hooks receive the item's values, not the current admin, so rules about who may do what belong in privileges. For example:

hooks: {
    beforeDelete: ({ values }) => {
        if (values.is_featured) {
            throw new Error('Featured posts can’t be deleted. Unfeature it first.')
        }
    },
}

Activity log

Every login, logout, create, update, delete, and admin change is recorded with the actor, the section, and the item. Admins with the log privilege can browse it on the Log page.

Security notes

  • Sessions use short-lived access tokens and long-lived refresh tokens (lifetimes set by ACCESS_TOKEN_EXPIRATION and REFRESH_TOKEN_EXPIRATION).
  • Every mutating request needs a valid CSRF token (checked in proxy.ts).
  • Admin passwords are stored bcrypt-hashed.
  • Changing ACCESS_TOKEN_SECRET or REFRESH_TOKEN_SECRET signs everyone out.