Users, Roles and Profiles

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This sub-section’s WordPress bibliography lists the reference material consulted while preparing these pages.

This page was written against WordPress 7.1.3 (released 2026-10-06; 7.1.4, a security release of 2026-10-28, is the version to run in production) and WP-CLI 2.12.0, and checked on 2026-10-28. WordPress 7.1 requires PHP 7.4 at minimum, and PHP 8.3 or newer is recommended. WordPress 7.2 is in beta and planned for 2026-12-08; nothing on this page is expected to change with it. Every command and capability list below was run against a fresh WordPress 7.1.3 site (official wordpress:7.1.3-php8.4-apache image, MariaDB 11.8, table prefix lp_), and every output block is real output with secrets replaced by placeholders and the test host name replaced by lumenpress.test or lumenpress.example. A disposable site for trying the commands is described in Local Development Environments.

This is the site owner’s view: which role to give each person, what each role can do, what users can change about themselves, and how to hand out credentials to tools. Creating roles and capabilities in code (add_role(), map_meta_cap, custom capabilities for a post type) is the developer’s side and is covered in Roles and Capabilities API.

The examples use the people of Lumen Press, the fictitious publisher used throughout this sub-section:

Login Role Job at Lumen Press

lp_admin

Administrator

The webmaster who installed the site, manages plugins, themes and settings

maria.editor

Editor

Fiction editor; reviews and publishes everyone’s posts, moderates comments

tom.author

Author

Staff writer of the news blog; publishes his own posts

ana.contrib

Contributor

Freelance reviewer; submits book reviews for approval

sam.reader

Subscriber

A newsletter reader with an account for comments and a reading list

Users, roles and capabilities

WordPress authorization has three layers:

  • a user is one row in the wp_users table (lp_users at Lumen Press) plus rows of user meta;

  • a role is a named set of capabilities. The built-in roles are stored in a single option, {prefix}user_roles (lp_user_roles), so a role is site data, not code;

  • a capability is a string such as publish_posts or manage_options. Code never asks "is this user an Editor?"; it asks "can this user edit_others_posts?" with current_user_can().

A user’s roles are stored in the user meta key {prefix}capabilities (lp_capabilities), which can also hold individual capabilities granted on top of the role. The legacy meta key {prefix}user_level and the level_0 to level_10 capabilities are kept only for backward compatibility with plugins written before WordPress 2.0; nothing in current core decides access by level. wp role list lists the roles and wp user meta get maria.editor lp_capabilities prints array ( 'editor' => true, ) for an Editor.

The six roles

Role Can do Typical person

Super Admin

Only exists on a Multisite network. Has every capability on every site, plus the network capabilities (create_sites, delete_sites, manage_network, manage_sites, manage_network_users, manage_network_plugins, manage_network_themes, manage_network_options, upgrade_network, setup_network)

The person running the whole network (Lumen Press, Lumen Kids, Lumen Noir)

Administrator

Everything on a single site: plugins, themes, settings, users, updates, import and export, plus all content

The webmaster

Editor

All content of all users: publish, edit and delete posts and pages, including private and published ones, manage categories and tags, moderate comments, post unfiltered HTML (single site)

Managing editor, section editors

Author

Write, publish, edit and delete their own posts, including after publishing, and upload media. No pages

Staff writers trusted to publish

Contributor

Write and edit their own posts while they are unpublished, and submit them for review. Cannot publish or upload

Freelancers, guest authors

Subscriber

Read, and manage their own profile

Registered readers, commenters, members

On a single site, the Administrator is in effect the Super Admin. On a Multisite network the site Administrator loses everything that changes files or the network: installing, updating and deleting plugins and themes, updating core, editing users across the network and unfiltered_html all require Super Admin. Super Admins are managed with wp super-admin (on a single site the command answers Error: This is not a multisite installation.); the network side is covered in Multisite Networks.

The capability matrix

The matrix below was produced from a fresh WordPress 7.1.3 site, one role at a time, with wp cap list <role>. It leaves out the eleven legacy level_N capabilities. The Administrator holds 61 capabilities (50 plus the levels level_0–level_10), the Editor 34, the Author 10, the Contributor 5 and the Subscriber 2 (read and level_0). Rows group capabilities that the five roles share in exactly the same way.

Capabilities Admin Editor Author Contrib. Subscr.

read

yes

yes

yes

yes

yes

edit_posts, delete_posts

yes

yes

yes

yes

–

publish_posts, edit_published_posts, delete_published_posts, upload_files

yes

yes

yes

–

–

edit_others_posts, delete_others_posts, edit_private_posts, read_private_posts, delete_private_posts

yes

yes

–

–

–

edit_pages, publish_pages, edit_published_pages, edit_others_pages, edit_private_pages, read_private_pages, delete_pages, delete_published_pages, delete_others_pages, delete_private_pages

yes

yes

–

–

–

moderate_comments, manage_categories, manage_links, unfiltered_html

yes

yes

–

–

–

manage_options, edit_dashboard, import, export

yes

–

–

–

–

unfiltered_upload (stored, but see below)

yes

–

–

–

–

switch_themes, edit_theme_options, install_themes, update_themes, delete_themes, edit_themes

yes

–

–

–

–

activate_plugins, install_plugins, update_plugins, delete_plugins, edit_plugins, edit_files, update_core

yes

–

–

–

–

list_users, create_users, edit_users, promote_users, remove_users, delete_users

yes

–

–

–

–

What the matrix does not show

A capability stored in a role is not always the final answer. Before checking the role, WordPress maps the requested capability through map_meta_cap(), and a few mappings matter to site owners:

  • unfiltered_upload is in the Administrator role, but current_user_can( 'unfiltered_upload' ) returned false for lp_admin on the test site: it is granted only when ALLOW_UNFILTERED_UPLOADS is defined in wp-config.php.

  • unfiltered_html (posting <script>, <iframe> and other markup that is normally stripped) is denied to everyone when DISALLOW_UNFILTERED_HTML is true, and on Multisite to everyone except Super Admins. Editors hold it on a single site, so an Editor account is as dangerous as an Administrator account if it is compromised: script in a post runs in the browser of every Administrator who opens it.

  • edit_plugins, edit_themes and edit_files disappear when DISALLOW_FILE_EDIT is set. DISALLOW_FILE_MODS additionally denies installing, updating and deleting plugins, themes and core. Both are covered in Security Hardening.

  • Per-object checks such as "may this user edit post 5?" use meta capabilities (edit_post, delete_post, read_post), which resolve to edit_posts, edit_others_posts or edit_published_posts depending on the author and status of that post.

The last point is easy to see on the Lumen Press site. Ana (Contributor) has a pending review, post 5:

for u in tom.author ana.contrib maria.editor; do
  wp eval --user="$u" '
    foreach ( array( "upload_files", "publish_posts" ) as $c ) {
      printf( "%s %s\n", $c, current_user_can( $c ) ? "yes" : "no" );
    }
    printf( "edit_post 5: %s\n", current_user_can( "edit_post", 5 ) ? "yes" : "no" );
  ' | sed "s/^/$u: /"
done
tom.author: upload_files yes
tom.author: publish_posts yes
tom.author: edit_post 5: no
ana.contrib: upload_files no
ana.contrib: publish_posts no
ana.contrib: edit_post 5: yes
maria.editor: upload_files yes
maria.editor: publish_posts yes
maria.editor: edit_post 5: yes

Tom can publish but cannot touch Ana’s post (it is someone else’s); Ana can edit her own post while it is pending; Maria can do both. How plugins add capabilities, write their own mappings and register roles is in Roles and Capabilities API.

Managing users

The Users screens

Users → All Users lists accounts with their name, email, role and post count, filter links per role, a search box (username, name, email and website) and Screen Options for the columns. Hovering a row shows Edit and Delete; the Change role to… drop-down changes the role of every checked user at once. Users → Add New User takes a username and email (both required and unique), first and last name, website, a generated password, the Send User Notification checkbox and the role, which defaults to New User Default Role from the General settings. Users → Profile is the current user’s own profile, described below.

Usernames cannot be changed from any screen, not even by an Administrator; the public name comes from Display name publicly as. The username still appears in author archive URLs (/author/<nicename>/), so a login such as admin tells attackers half of the credentials. Usernames are also printed on these screens, and until WordPress 7.1.4 (2026-10-28) a specially crafted user login could cause stored XSS there; the 7.1.4 security release fixes it, which matters most on sites with open registration (WordPress News: WordPress 7.1.4).

The same tasks with WP-CLI

wp user create maria.editor maria@lumenpress.example --role=editor \
  --first_name=Maria --last_name=Ortega --display_name="Maria Ortega" --porcelain
wp user create tom.author tom@lumenpress.example --role=author --porcelain
wp user create ana.contrib ana@lumenpress.example --role=contributor --porcelain
wp user create sam.reader sam@lumenpress.example --porcelain
wp user list --fields=ID,user_login,display_name,roles
2
3
4
5
+----+--------------+--------------+---------------+
| ID | user_login   | display_name | roles         |
+----+--------------+--------------+---------------+
| 4  | ana.contrib  | ana.contrib  | contributor   |
| 1  | lp_admin     | lp_admin     | administrator |
| 2  | maria.editor | Maria Ortega | editor        |
| 5  | sam.reader   | sam.reader   | subscriber    |
| 3  | tom.author   | tom.author   | author        |
+----+--------------+--------------+---------------+

wp user create without --role uses the default_role option (subscriber here), and without --user_pass it generates a password; with --porcelain it prints only the new ID, otherwise it prints the generated password once. --send-email mails the new user their login details. wp user set-role tom.author editor replaces the role (it prints Success: Added tom.author (3) to <site> as editor.), while wp user add-role adds a second one; core screens show and edit a single role, so multiple roles are best left to plugins that manage them explicitly.

Deleting a user and their content

Deleting a user asks what to do with their content: Delete all content or Attribute all content to another user. Choosing the first deletes every post, page and attachment the user authored, including published ones, so for anyone who has ever written content, attribute it. With WP-CLI the choice is --reassign; without it the content is deleted after a confirmation prompt:

wp user delete ana.contrib --reassign=2
wp post list --post_status=pending --fields=ID,post_title,post_author
Success: Removed user 4 from http://lumenpress.test.
+----+--------------------------+-------------+
| ID | post_title               | post_author |
+----+--------------------------+-------------+
| 5  | Autumn catalogue preview | 2           |
+----+--------------------------+-------------+

For a person who leaves but whose name should stay on their articles, the alternative is to keep the account, change it to Subscriber, reset its password and revoke its application passwords and sessions. Requests to erase a person’s personal data follow the privacy tools described in SEO, Analytics and Privacy.

Registration settings

Two settings on Settings → General control who may create their own account:

Setting Option Effect

Membership: Anyone can register

users_can_register (0 by default)

Shows the Register link and enables wp-login.php?action=register. When off, that URL redirects to wp-login.php?registration=disabled. The old wp-register.php no longer exists; requests to it are redirected (301) to the registration form

New User Default Role

default_role (subscriber by default)

The role given to self-registered users and preselected on Add New User

Open registration should only be enabled with Subscriber as the default role. A default role of Contributor or higher lets anyone on the internet create content in the admin, and a default of Editor or Administrator hands over the site; compromised sites are sometimes found with default_role changed to administrator and registration turned on, so both values are worth checking after an incident (wp option get users_can_register and wp option get default_role print 0 and subscriber on a default install). Registration forms also attract automated sign-ups: an anti-spam or CAPTCHA plugin, or email confirmation through a membership plugin, is the usual answer. Lumen Press keeps registration closed and creates staff accounts by hand.

The Administration Email Address on the same screen is not a user account. Changing it sends a confirmation link to the new address, and the old address stays active until the link is clicked. Multisite networks have their own registration options (users, sites, both or none) on Network Admin → Settings, covered in Multisite Networks.

Profile fields

Every user, whatever their role, can open Users → Profile (or the name in the top-right of the toolbar). An Administrator editing another user sees the same screen plus the Role drop-down. The fields and where they are stored:

Section and field Stored as Notes

Personal Options

Visual Editor

user meta rich_editing

Turns off the visual editor in the classic editor

Syntax Highlighting

user meta syntax_highlighting

Code editors in the theme and plugin file editors

Administration Color Scheme

user meta admin_color

Since 7.0 the default is modern, labelled Default; the previous default is Fresh (fresh). Others: Light, Blue, Midnight, Sunrise, Ectoplasm, Ocean, Coffee

Keyboard Shortcuts

user meta comment_shortcuts

Comment-moderation shortcuts

Toolbar

user meta show_admin_bar_front

The admin bar on the front end

Infinite Scrolling

user meta infinite_scrolling

Per-user choice for the Media Library grid view

Language

user meta locale

Admin language for this user only; empty means the site language

Name

Username

user_login column

Cannot be changed

First Name, Last Name

user meta first_name, last_name

Nickname (required)

user meta nickname

Defaults to the username

Display name publicly as

display_name column

Chosen from username, nickname, first, last, "first last", "last first"

Contact Info

Email (required)

user_email column

Unique per user. Changing it sends a confirmation link to the new address and keeps the old one until it is confirmed (the pending address is in user meta _new_email)

Website

user_url column

Extra contact methods

user meta

Added by plugins and themes with the user_contactmethods filter

About Yourself

Biographical Info

user meta description

Shown by themes in author boxes and the Post Author Biography block

Profile Picture

not stored

Comes from Gravatar, keyed by a hash of the email address

Account Management

New Password

user_pass column (hashed)

Set New Password generates a strong one; see below

Sessions

user meta session_tokens

Log Out Everywhere Else destroys every other session

Application Passwords

Name, list, revoke

user meta _application_passwords

Hidden when the feature is unavailable; see below

The same values can be read and changed from the shell, for example to reset an Editor’s colour scheme:

wp user meta update maria.editor admin_color fresh
wp user meta get maria.editor admin_color
Success: Updated custom field 'admin_color'.
fresh

Gravatar URLs use HTTPS unconditionally since 6.7 and a SHA-256 hash of the lower-cased email since 6.8 (an MD5 hash before). Avatars can be switched off, and the default image and maximum rating chosen, under Settings → Discussion (options show_avatars, avatar_default, avatar_rating). Because the hash is derived from the email address, showing Gravatars discloses a stable identifier for every commenter to a third party; the privacy policy should say so (see SEO, Analytics and Privacy).

Passwords, sessions and two-factor authentication

Password strength. The profile and Add New User screens generate a strong random password and show a strength meter (based on the zxcvbn library) as the user types. Core does not enforce a minimum strength: choosing a weak password only shows a Confirm use of weak password checkbox. Sites that need a policy enforce it with a plugin or with SSO.

Hashing. Since 6.8, passwords are hashed with bcrypt instead of phpass. WordPress pre-hashes the password with SHA-384 (bcrypt reads only 72 bytes), which is what the $wp$2y$ prefix in user_pass marks; existing phpass hashes keep working and are rehashed the next time the user logs in. On the test site every hash starts with that prefix:

wp db query "SELECT user_login, LEFT(user_pass, 7) AS prefix FROM lp_users"
+--------------+---------+
| user_login   | prefix  |
+--------------+---------+
| lp_admin     | $wp$2y$ |
| maria.editor | $wp$2y$ |
| tom.author   | $wp$2y$ |
| ana.contrib  | $wp$2y$ |
| sam.reader   | $wp$2y$ |
+--------------+---------+

Resetting a password. Users reset their own through Lost your password? on wp-login.php, which emails a reset link (so outgoing mail must work, see Email Delivery). An Administrator can send the same link from the user’s row (Send password reset) or set a password on the user’s profile. With shell access, WP-CLI is the reliable route:

wp user update ana.contrib --user_pass='<new-password>' --skip-email
wp user reset-password sam.reader --skip-email --show-password
Success: Updated user 4.
Reset password for sam.reader.
Password: <shown once>
Success: Password reset for 1 user.

Writing an MD5 hash into user_pass with phpMyAdmin, the classic lock-out remedy, still works because WordPress accepts the old format once and rehashes it, but it is a legacy path that leaves a weak hash in the database until the next login. WP_ALLOW_REPAIR has nothing to do with passwords: it opens /wp-admin/maint/repair.php to anyone, without a login, and only repairs and optimizes tables.

Sessions. Each login creates a session token stored in the user’s session_tokens meta. Log Out Everywhere Else on the profile (or Log Out Everywhere when an Administrator views another user) destroys them. Changing the password also invalidates existing login cookies, because they are derived partly from the password hash. From the shell, wp user session list ana.contrib lists a user’s sessions and wp user session destroy ana.contrib --all ends them (it answers Success: Destroyed all sessions.); see WP-CLI Commands: wp user session.

Two-factor authentication. WordPress core has no two-factor authentication. It is added with a plugin; the canonical one is Two Factor, maintained by WordPress.org contributors, which offers authenticator-app (TOTP) codes, email codes and backup codes, with passkeys and security keys through a companion WebAuthn provider plugin. Single sign-on through an identity provider is the other common route. Lumen Press requires TOTP for the Administrator and Editors, because both roles can post unfiltered HTML. Login hardening (limiting attempts, XML-RPC) is in Security Hardening, and the methods themselves in Authentication Methods: Passwordless and 2FA.

Application passwords

Application passwords (since 5.6) let a script, a mobile app or another site call the REST API or XML-RPC as a user without knowing that user’s real password. Each one is a 24-character random password, shown once (grouped as six blocks of four for readability; the spaces are ignored), named after the application that uses it, and revocable on its own. They cannot be used to log in to wp-login.php, and no second factor is asked for when they are used, which is why they must be treated as secrets with the full power of the user who created them.

Where to create them. On Users → Profile → Application Passwords: type a name (for example "Lumen reader app"), click Add New Application Password, and copy the password from the notice. The list below the form shows each password’s name, creation date, last use and last IP, with a Revoke button per row and Revoke all application passwords. Administrators can do the same on another user’s profile.

When they are available. By default only when the site is served over HTTPS or WP_ENVIRONMENT_TYPE is local; on a plain-HTTP production site the section is missing from the profile. The check in WordPress 7.1.3:

function wp_is_application_passwords_supported() {
	return is_ssl() || 'local' === wp_get_environment_type();
}

The whole feature can be turned off with the wp_is_application_passwords_available filter, or restricted per user with wp_is_application_passwords_available_for_user. Lumen Press allows them only for staff who can write; this must-use plugin (wp-content/mu-plugins/lumen-app-passwords.php) hides the section from Subscribers and makes their existing application passwords stop working:

<?php
/**
 * Plugin Name: Lumen Application Password Policy
 * Description: Only staff who can edit posts may create or use application passwords.
 */

add_filter(
	'wp_is_application_passwords_available_for_user',
	static function ( $available, $user ) {
		return $available && user_can( $user, 'edit_posts' );
	},
	10,
	2
);

With the plugin active, wp_is_application_passwords_available_for_user() returned "not available" for sam.reader and "available" for tom.author, and a REST request with an application password of sam.reader was rejected with 401. WP-CLI does not apply the filter when creating a password, so the policy limits use, not creation from the shell.

Creating, using and revoking them with WP-CLI

The wp user application-password command (WP-CLI 2.6+) has create, list, get, exists, update, record-usage and delete subcommands:

APP_PASSWORD="$(wp user application-password create maria.editor "Lumen reader app" --porcelain)"
wp user application-password create maria.editor "Newsletter sync" \
  --app-id=1b0c8f0e-6f4e-4b44-9a1d-3a6f2a6c1f11
wp user application-password exists maria.editor "Lumen reader app" && echo "exists"
wp user application-password list maria.editor --fields=uuid,name,app_id
Success: Created application password.
Password: <shown once>
exists
+--------------------------------------+------------------+--------------------------------------+
| uuid                                 | name             | app_id                               |
+--------------------------------------+------------------+--------------------------------------+
| a50c6413-4491-48d3-afb0-0b987eab602d | Newsletter sync  | 1b0c8f0e-6f4e-4b44-9a1d-3a6f2a6c1f11 |
| 32182fba-8377-4cdf-8ec6-7f0c5c2ecff3 | Lumen reader app |                                      |
+--------------------------------------+------------------+--------------------------------------+

The password field of the list, and the _application_passwords user meta, hold only a hash: since 6.8 application passwords are hashed with BLAKE2b (prefix $generic$) rather than bcrypt, because they are long random strings checked on every API request. A lost application password cannot be recovered, only revoked and replaced.

A client sends the username and application password with HTTP Basic authentication. Lumen Press’s reader app checks who it is connected as:

curl -s -u "maria.editor:$APP_PASSWORD" \
  "https://lumenpress.example/wp-json/wp/v2/users/me?context=edit&_fields=id,name,roles"
{"id":2,"name":"Maria Ortega","roles":["editor"]}

After the call, list shows when and from where the password was last used, which is how unused or leaked passwords are spotted. One revoked password does not affect the others:

wp user application-password list maria.editor --fields=name,created,last_used,last_ip
wp user application-password delete maria.editor a50c6413-4491-48d3-afb0-0b987eab602d
wp user application-password delete ana.contrib --all
+------------------+------------+------------+------------+
| name             | created    | last_used  | last_ip    |
+------------------+------------+------------+------------+
| Newsletter sync  | 1793182883 |            |            |
| Lumen reader app | 1793182882 | 1793182893 | 172.22.0.4 |
+------------------+------------+------------+------------+
Success: Deleted 1 of 1 application password.
Success: Deleted all application passwords.

The same password also worked for an XML-RPC wp.getProfile call on the test site, and an attempt to log in at wp-login.php with it failed. A wrong or unavailable application password on /wp/v2/users/me returned the same 401 rest_not_logged_in as a request with no credentials, so clients cannot tell a typo from a revoked password by the response alone.

Letting an application ask for a password

Instead of asking users to copy a password by hand, an application can send them to /wp-admin/authorize-application.php with app_name (required), app_id (a UUID identifying the application), success_url and reject_url. The user logs in, reviews the request and approves it; WordPress then redirects to success_url with site_url, user_login and password appended. Without success_url the password is shown on screen. Because the password travels in it, success_url may not be plain http:// unless the site is a local environment or the URL points to 127.0.0.1 or [::1]; custom schemes for mobile apps are accepted, while javascript: and data: are rejected.

https://lumenpress.example/wp-admin/authorize-application.php?app_name=Lumen%20reader%20app&app_id=6f1d0c4e-2a51-4e0b-9a7c-1c2d3e4f5a6b&success_url=https%3A%2F%2Freader.lumenpress.example%2Fconnected

Pitfalls

  • Missing Authorization header. Some proxies, CDNs and PHP-CGI/FastCGI setups drop the header, and every request then looks anonymous. The fix is in the web server or proxy configuration (see Web Servers: Apache and nginx).

  • Over-powerful credentials. An application password has every capability of its user. Create a dedicated user with the lowest role that works (an Author for a tool that only publishes posts) instead of using the Administrator’s.

  • Rotation. Revoke passwords that have not been used for a long time, after a staff member leaves, and after any suspected leak; check last_used and last_ip regularly.

  • Not for browsers. JavaScript running in the WordPress admin authenticates with the login cookie and a wp_rest nonce, not with application passwords; see REST API: Using It.

A multi-author editorial workflow

The built-in roles already describe a simple newsroom. At Lumen Press:

  1. Ana (Contributor) drafts a book review and clicks Submit for Review; the post status becomes pending. She cannot publish, upload images or edit the review after it is published.

  2. Maria (Editor) filters Posts by Pending, edits the text, adds the featured image Ana could not upload, and publishes or schedules it. She leaves feedback in the editor with Notes (see Block Editor for Authors).

  3. Tom (Author) writes news posts and publishes them himself; he can edit them after publication but cannot edit Ana’s or Maria’s posts.

  4. Maria also moderates comments on every post; Tom and Ana see comments but cannot approve them.

The REST API enforces the same rules. Ana’s application password can create a pending post but not a published one:

ANA_APP_PASSWORD="$(wp user application-password create ana.contrib "Drafting tool" --porcelain)"
curl -s -u "ana.contrib:$ANA_APP_PASSWORD" -X POST https://lumenpress.example/wp-json/wp/v2/posts \
  -d title='Autumn catalogue preview' -d status=publish
curl -s -u "ana.contrib:$ANA_APP_PASSWORD" -X POST https://lumenpress.example/wp-json/wp/v2/posts \
  -d title='Autumn catalogue preview' -d status=pending -d _fields=id,status,author
{"code":"rest_cannot_publish","message":"Sorry, you are not allowed to publish posts in this post type.","data":{"status":403}}
{"id":5,"status":"pending","author":4}

The statuses and scheduling are explained in Posts and Pages. Core has no notification when a post is submitted for review, no editorial calendar, no custom statuses (such as "in copy-edit") and no per-category permissions. Those come from editorial workflow plugins, or from custom roles and capabilities in a plugin. Two practical consequences of the defaults:

  • Contributors cannot upload media, so their posts arrive without images; either an Editor adds them or the site grants upload_files to Contributors (a capability change, done in code).

  • An Author can unpublish or delete their own published posts, which some publishers do not want; the Contributor role plus an Editor’s review avoids that.

The Catalogue Manager role (planned)

The book catalogue (lp_book posts with the lp_genre and lp_series taxonomies, added by the lumen-catalog plugin) is maintained by a sales assistant who must not touch the news blog, pages or settings. No built-in role fits: an Author cannot edit books entered by others, and an Editor could rewrite every news post and page. Lumen Press therefore defines a Catalogue Manager role that may read the admin, upload cover images, create, edit, publish and delete any book (including other people’s) and manage genre and series terms, but has no access to posts, pages, comments, plugins, themes, settings, users or unfiltered HTML.

This needs capabilities of its own for the book post type rather than the post capabilities, and a role created once when the plugin is activated, not on every request. Both are implemented in Roles and Capabilities API. Plugins that edit roles from the admin exist for sites without a developer, but they write the same lp_user_roles option and survive deactivation, so a role created with them should be documented like any other configuration.

Where older books are outdated

Older claim Current behaviour (WordPress 7.1)

WordPress includes, or can be configured for, two-factor authentication on its own

Core has none. Two-factor authentication comes from a plugin (Two Factor is the reference implementation) or SSO

Defining WP_ALLOW_REPAIR helps recover a lost password

It only repairs and optimizes database tables, and exposes the repair page without login while defined. Use Lost your password?, wp user update --user_pass or wp user reset-password

Resetting a password by writing an MD5 hash in phpMyAdmin

Still accepted and rehashed at the next login, but legacy; passwords are hashed with bcrypt since 6.8

WordPress enforces strong passwords

It only shows a strength meter and asks to confirm a weak one

A custom role is registered with add_role() on every init

It is stored in the database and created once, on plugin activation (see Roles and Capabilities API)

Users register at wp-register.php

Registration is at wp-login.php?action=register; the old address only redirects there