Skip to content

fix(permissions): allow team-member contributors to use event/venue write abilities#291

Merged
chubes4 merged 3 commits into
mainfrom
fix-288-team-member-permissions
May 20, 2026
Merged

fix(permissions): allow team-member contributors to use event/venue write abilities#291
chubes4 merged 3 commits into
mainfrom
fix-288-team-member-permissions

Conversation

@chubes4
Copy link
Copy Markdown
Member

@chubes4 chubes4 commented May 20, 2026

Closes #288.

Summary

Every write ability in this plugin gated on current_user_can( 'manage_options' ), which locked out team-member contributors like Chris Gardner (qrisg, ID 38 — extrachill_team=1, no WP role on events.extrachill.com). The Roadie chat agent already treats team members as authorized via extrachill_roadie_team_access_bridge, but every underlying ability rejected them. Concrete blocker: qrisg couldn't resolve merged-bill duplicates via chat, even though Roadie offered him the tools.

This PR implements Option A from the issue body: a shared closure factory that combines WP_CLI, an ec_is_team_member() override, and an edit_others_posts fallback.

Helper introduced

DataMachineEvents\Abilities\AbilityPermissions (inc/Abilities/AbilityPermissions.php) exposes two static closure factories:

  • AbilityPermissions::canWrite()WP_CLIec_is_team_member()current_user_can('edit_others_posts')
  • AbilityPermissions::canRead()WP_CLIec_is_team_member()current_user_can('edit_posts') (provided for future use; not consumed by this PR)

ec_is_team_member() is wrapped in function_exists() so the plugin still loads when extrachill-users is absent (tests, isolated CLI). The file is require_once-d from data-machine-events.php immediately after AbilityCategories, so every ability registration that runs later can reference it without further bootstrapping.

Every modified ability now reads as a single line:

'permission_callback' => AbilityPermissions::canWrite(),

Ability files touched

File Abilities
inc/Abilities/EventUpdateAbilities.php update-event
inc/Abilities/MergeEventPostsAbilities.php merge-event-posts
inc/Abilities/MergedBillDecideAbilities.php merged-bill-inspect, merged-bill-decide
inc/Abilities/VenueAbilities.php venue-health-check, update-venue, get-venue, check-duplicate-venue
inc/Abilities/BatchTimeFixAbilities.php batch-time-fix
inc/Abilities/TimezoneAbilities.php find-broken-timezone-events, fix-event-timezone
inc/Abilities/EncodingFixAbilities.php encoding-fix
inc/Abilities/GeocodingAbilities.php geocode-address, geocode-venues, audit-venues (also drops redundant inline WP_CLI checks)
inc/Abilities/TicketUrlResyncAbilities.php resync-ticket-urls
inc/Abilities/MetaSyncAbilities.php find-missing-meta-sync, resync-event-meta

Plus the loader wiring in data-machine-events.php and the new helper at inc/Abilities/AbilityPermissions.php.

Read-only abilities intentionally left alone

The issue body said: "Read-only abilities (event-query, venue-stats, event-health, audits) likely stay as-is or open up further — separate decision." So this PR does not touch:

  • EventHealthAbilities (event-health-check) — still admin-gated
  • EventQualityAuditAbilities (event-quality-audit) — still admin-gated
  • EventQueryAbilities (get-venue-events) — still admin-gated
  • VenueStatsAbilities (venue-stats) — still admin-gated (already had WP_CLI exemption)
  • DuplicateDetectionAbilities (find-duplicate-event) — still admin-gated
  • MergedBillDetectAbilities (detect-merged-bill) — still admin-gated
  • SettingsAbilities (get-settings, update-setting) — still admin-gated (settings touch is sensitive)
  • EventScraperTest, DiceFmTest, TicketmasterTest — still admin-gated (debug/diagnostic)

These are out of scope per the issue. They can be opened up in a follow-up if Roadie needs team members to call them as well.

Why some VenueAbilities read abilities were opened up

VenueAbilities registers four abilities in one file (venue-health-check, update-venue, get-venue, check-duplicate-venue). The issue explicitly lists VenueAbilities for the write fix, and all four are part of the same Roadie venue-edit flow (look up the venue → check for duplicates → update). Opening them as a group keeps the permission shape consistent and matches the "venue create/update/delete" scope in the issue. Same reasoning for find-broken-timezone-events (precursor to fix-event-timezone) and merged-bill-inspect (precursor to merged-bill-decide).

How to verify

Run on events.extrachill.com after this branch is deployed (or against any subsite where the target user is a contributor with extrachill_team=1):

wp --allow-root --path=/var/www/extrachill.com --url=events.extrachill.com \
   eval 'wp_set_current_user(38); var_dump( wp_get_ability( "data-machine-events/update-event" )->has_permission() );'

Expected: bool(true).

Before this PR the same snippet returned bool(false) (qrisg has no WP role on the events subsite, so current_user_can('manage_options') was false). With this PR, ec_is_team_member() returns true for user 38 and the override fires.

A separate sanity check against admin (user 1) should still return bool(true) because admins have edit_others_posts:

wp --allow-root --path=/var/www/extrachill.com --url=events.extrachill.com \
   eval 'wp_set_current_user(1); var_dump( wp_get_ability( "data-machine-events/update-event" )->has_permission() );'

And for a true outsider (any non-team subscriber):

wp --allow-root --path=/var/www/extrachill.com --url=events.extrachill.com \
   eval 'wp_set_current_user( /* some non-team user id */ ); var_dump( wp_get_ability( "data-machine-events/update-event" )->has_permission() );'

Expected: bool(false).

Notes

cc <@532385681268408341>

homeboy-ci Bot added 3 commits May 20, 2026 23:28
…lbacks

Introduces DataMachineEvents\Abilities\AbilityPermissions::canWrite() and
canRead() closures that combine WP_CLI, ec_is_team_member() override, and a
fallback capability check (edit_others_posts for writes, edit_posts for
reads). Wraps ec_is_team_member() in function_exists() so the plugin still
loads when extrachill-users is absent (tests, isolated CLI).

Wired the require into data-machine-events.php so every ability can call
the static factory without further bootstrapping.

Refs #288.
Replaces current_user_can('manage_options') gates with
AbilityPermissions::canWrite() on event and venue mutation abilities, so
contributors with extrachill_team=1 user meta (e.g. qrisg, ID 38) can
exercise the corresponding chat tools (update_event, merged_bill_inspect,
merged_bill_decide, update_venue, venue_health_check, get_venue,
check_duplicate_venue) and the merge-event-posts pairwise merge.

Files touched:
- inc/Abilities/EventUpdateAbilities.php (update-event)
- inc/Abilities/MergeEventPostsAbilities.php (merge-event-posts)
- inc/Abilities/MergedBillDecideAbilities.php (merged-bill-inspect, merged-bill-decide)
- inc/Abilities/VenueAbilities.php (venue-health-check, update-venue, get-venue, check-duplicate-venue)

Closes #288.
Same shape: AbilityPermissions::canWrite() in place of admin-only gates so
team-member contributors can run the maintenance and sweep tools alongside
their event/venue edits.

Files touched:
- inc/Abilities/BatchTimeFixAbilities.php (batch-time-fix)
- inc/Abilities/EncodingFixAbilities.php (encoding-fix)
- inc/Abilities/TicketUrlResyncAbilities.php (resync-ticket-urls)
- inc/Abilities/MetaSyncAbilities.php (find-missing-meta-sync, resync-event-meta)
- inc/Abilities/TimezoneAbilities.php (find-broken-timezone-events, fix-event-timezone)
- inc/Abilities/GeocodingAbilities.php (geocode-address, geocode-venues, audit-venues)

GeocodingAbilities also drops a redundant inline WP_CLI check since canWrite() handles it centrally.

Refs #288.
@homeboy-ci
Copy link
Copy Markdown
Contributor

homeboy-ci Bot commented May 20, 2026

Homeboy Results — data-machine-events

Audit

audit — passed

  • requested_detectors — 19 finding(s)
  • test_coverage — 10 finding(s)
  • intra-method-duplication — 8 finding(s)
  • repeated_literal_shape — 2 finding(s)
  • Abilities — 1 finding(s)
  • Total: 40 finding(s)

Deep dive: homeboy audit data-machine-events --changed-since 1012091

Tooling versions
  • Homeboy CLI: homeboy 0.194.0+b421274
  • Extension: wordpress from https://github.com/Extra-Chill/homeboy-extensions
  • Extension revision: edb75b19
  • Action: Extra-Chill/homeboy-action@v2

@chubes4 chubes4 merged commit fa857db into main May 20, 2026
1 check passed
chubes4 added a commit that referenced this pull request May 20, 2026
… move-event ability (#292)

Follow-up to #290 — adopts the shared AbilityPermissions::canWrite()
helper introduced by #288/#291. #290 merged before the helper landed,
so the move-event ability shipped with a manage_options stub and a
TODO referencing #288. This swaps it to the helper to match the rest
of the EC-events surface (e.g. EventUpdateAbilities) and removes the
stale TODO.

No functional change beyond the permission_callback shape.

Refs #287, #288, #290.

Co-authored-by: homeboy-ci[bot] <266378653+homeboy-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

audit(permissions): event/venue write abilities require manage_options, locking out team-member contributors

1 participant