User Teams

Sharraxaad

On a large multisite network, granting a group of people the same role across many sites usually means adding each user to each site by hand — and remembering to remove them everywhere when they leave. User Teams turns that into:

  1. Create a team, pick a role.
  2. Add the user to the team.
  3. They have that role everywhere the team applies.
  4. Remove them from the team access is gone everywhere.

User Teams is multisite-only by design — on a single-site install, native WordPress roles and capabilities already cover the whole feature set, so WordPress won’t offer it for activation there.

Features

  • Teams with roles. Each team carries a WordPress role (editor, administrator, a custom role, or none).
  • Runtime capability grants. Team access is added via the user_has_cap filter, so removing a user from a team drops their access on the next request — no stale capabilities usermeta to clean up.
  • Multisite-native. Team definitions are real wp_users rows (“team accounts”), so WP_Users_List_Table, is_user_member_of_blog(), and every column-adding plugin “just work”.
  • Site scoping. A team can apply network-wide (including sites added later) or to a specific list of sites, each with its own role.
  • Admin UI. Network Admin Users Teams. Per-user checkboxes on the Edit User screen. Team rows with “— Team” markers on the Users list table.
  • Cleans up after itself. Deleting a team removes its memberships. Deleting a user drops their memberships. Deleting a site removes its grants from any team that targeted it.

How access is granted

Team-derived capabilities are merged in at runtime, never written into the member user’s own meta:

  • user_has_cap — adds the team role’s capabilities to the user’s effective caps, plus role-{slug} for plugins that check by role.
  • get_blogs_of_user — adds team-linked sites to the user’s “My Sites” navigation.
  • get_user_metadata — returns an empty-array {prefix}{blog_id}_capabilities for team members so is_user_member_of_blog() returns true without stamping real capabilities on the user. Workaround for Core #65096.

The user’s actual {prefix}capabilities usermeta is never modified. That’s what makes team-based access instantly revocable.

Capability requirements

  • Managing teams (create / edit / delete) requires manage_network_users — super admin only.
  • Attaching an existing team to the current site uses promote_users, the same cap as inviting an individual user there.

Team management is restricted to super admins so a compromised single-site admin can’t grant themselves access across the network.

Extension filters

  • user_teams_team_caps_for_user( $caps, $user_id, $blog_id ) — modify the capability map computed from a user’s teams.
  • user_teams_team_applies_to_site( $applies, $team_id, $blog_id, $team ) — gate coverage (e.g. pause a team during a freeze).
  • user_teams_team_save_data( $data, $team_id_or_null, $op ) — filter sanitised input on create/update.

SBI

Does this work on a single-site install?

No. On a single-site install, native roles and capabilities already cover the whole feature set, so the plugin is marked Network: true and WordPress won’t offer it for activation.

What happens to a user’s role when they’re removed from a team?

Nothing is persisted on the user, so removing them from the team drops the team-derived capabilities on the next request. The user’s own native role on each site is untouched.

Where are teams stored?

Each team is a real wp_users row (a “team account”) marked with user_teams_is_team meta. Per-site role grants use native wp_{blog_id}_capabilities meta on that row. Memberships are on the member user’s own user_teams meta. No custom tables.

How do I create a team programmatically?

use dd32\WordPress\UserTeams\Plugin;

$id = Plugin::create_team( 'Meta Team', 'meta-team', 'editor' );
Plugin::add_team_to_site( $id, 1, 'editor' );
Plugin::add_team_to_site( $id, 4, 'author' );
Plugin::add_user_to_team( $user_id, $id );

Checking access uses the normal cap system — team-derived caps participate via user_has_cap:

if ( user_can( $user_id, 'edit_others_posts' ) ) {
    // ...
}

Where’s development happening?

On GitHub at dd32/wp-user-teams. That’s where the source, issues, pull requests, and release tags live.

I have a bug report or feature request

File it on GitHub. General support questions belong in the WordPress.org Support Forums.

How do I report a security issue?

Please report security issues privately via GitHub Security Advisories. Do not file public issues or post to the support forums for security reports.

Dibu-eegisyo

Ma jiraan wax dibu-eegis ah oo ku saabsan kaabahan.

Ka-qaybgalayaasha & Horumariyayaasha

“User Teams” waa softiweer il furan. Dadka soo socda ayaa wax ku biiriyay kaabahan.

Ka-qaybgalayaasha

Ku tarjun “User Teams” luqaddaada.

Ma xiisaynaysaa horumarinta?

Baadh koodka, fiiri bakhaarka SVN, ama iska qor diiwaanka horumarinta adigoo adeegsanaya RSS.

Isbeddellada

0.5.1

  • Security: scope the pre_user_query team-member injection to the admin Users screens so a public WP_User_Query (e.g. the REST users collection) can’t be broadened by ?team=N.

0.5

  • Initial WordPress.org release.