fix(permissions): allow team-member contributors to use event/venue write abilities#291
Merged
Merged
Conversation
…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.
Contributor
Homeboy Results —
|
This was referenced May 20, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 onevents.extrachill.com). The Roadie chat agent already treats team members as authorized viaextrachill_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, anec_is_team_member()override, and anedit_others_postsfallback.Helper introduced
DataMachineEvents\Abilities\AbilityPermissions(inc/Abilities/AbilityPermissions.php) exposes two static closure factories:AbilityPermissions::canWrite()—WP_CLI∨ec_is_team_member()∨current_user_can('edit_others_posts')AbilityPermissions::canRead()—WP_CLI∨ec_is_team_member()∨current_user_can('edit_posts')(provided for future use; not consumed by this PR)ec_is_team_member()is wrapped infunction_exists()so the plugin still loads whenextrachill-usersis absent (tests, isolated CLI). The file isrequire_once-d fromdata-machine-events.phpimmediately afterAbilityCategories, so every ability registration that runs later can reference it without further bootstrapping.Every modified ability now reads as a single line:
Ability files touched
inc/Abilities/EventUpdateAbilities.phpupdate-eventinc/Abilities/MergeEventPostsAbilities.phpmerge-event-postsinc/Abilities/MergedBillDecideAbilities.phpmerged-bill-inspect,merged-bill-decideinc/Abilities/VenueAbilities.phpvenue-health-check,update-venue,get-venue,check-duplicate-venueinc/Abilities/BatchTimeFixAbilities.phpbatch-time-fixinc/Abilities/TimezoneAbilities.phpfind-broken-timezone-events,fix-event-timezoneinc/Abilities/EncodingFixAbilities.phpencoding-fixinc/Abilities/GeocodingAbilities.phpgeocode-address,geocode-venues,audit-venues(also drops redundant inlineWP_CLIchecks)inc/Abilities/TicketUrlResyncAbilities.phpresync-ticket-urlsinc/Abilities/MetaSyncAbilities.phpfind-missing-meta-sync,resync-event-metaPlus the loader wiring in
data-machine-events.phpand the new helper atinc/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-gatedEventQualityAuditAbilities(event-quality-audit) — still admin-gatedEventQueryAbilities(get-venue-events) — still admin-gatedVenueStatsAbilities(venue-stats) — still admin-gated (already hadWP_CLIexemption)DuplicateDetectionAbilities(find-duplicate-event) — still admin-gatedMergedBillDetectAbilities(detect-merged-bill) — still admin-gatedSettingsAbilities(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
VenueAbilitiesread abilities were opened upVenueAbilitiesregisters four abilities in one file (venue-health-check,update-venue,get-venue,check-duplicate-venue). The issue explicitly listsVenueAbilitiesfor 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 forfind-broken-timezone-events(precursor tofix-event-timezone) andmerged-bill-inspect(precursor tomerged-bill-decide).How to verify
Run on
events.extrachill.comafter this branch is deployed (or against any subsite where the target user is a contributor withextrachill_team=1):Expected:
bool(true).Before this PR the same snippet returned
bool(false)(qrisg has no WP role on the events subsite, socurrent_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 returnbool(true)because admins haveedit_others_posts:And for a true outsider (any non-team subscriber):
Expected:
bool(false).Notes
delete_eventchat tool) and feat(chat-tools): add move_event primitive (single-call venue change with audit trail) #287 (move_eventchat tool); both will reuseAbilityPermissions::canWrite().cc <@532385681268408341>