Completes the instructor-management half of #9: the studio admin can now create instructor accounts and toggle each instructor's capabilities. - InstructorController (manage_instructors): list instructors, create a us_instructor WP user (emailing a set-password link), and a per-instructor capability detail view. - InstructorCapabilities: pure, unit-tested rules for which managed caps an admin may assign and how a submitted form maps to assignments. Managed caps are manage_offerings, manage_questions, view_own_payments, export_payments; manage_availability and view_own_lessons are core to every instructor. - A studio admin can never grant a capability it does not itself hold: only held caps (checked via current_user_can, so an administrator's dynamic grant counts) are offered, and on creation any managed cap the admin lacks is denied on the new instructor so they never exceed their creator. The role grants the managed caps by default; the page layers per-user overrides. - AdminMenu: register the Instructors page in the people section. - Tests for the capability logic; docs/features/user-roles.md updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.7 KiB
Feature: User Roles
Overview
Three custom WordPress user roles control access to all scheduling features: a studio admin who runs the business, instructors who teach, and students who book.
Roles
Studio Admin (us_studio_admin)
Runs the studio. Logs in via standard wp-admin. Can:
- Create instructor accounts and set/revoke each instructor's capabilities
- Manage offerings, intake questions, and policies
- Configure Stripe credentials and per-student billing overrides (card / e-transfer / comp)
- View the studio-wide scheduler (all upcoming lessons across instructors)
- View the all-instructor payments report and export it
Capabilities: read, manage_instructors, manage_offerings, manage_questions, manage_policies, manage_billing, view_all_lessons, view_all_payments, export_payments
Any WordPress administrator (
manage_options) implicitly holds every studio-admin capability above and the instructor capabilities (notablymanage_availability), so a single-instructor studio owner can run the business and teach — managing their own availability and lessons — from one account, without being assigned theus_studio_adminorus_instructorrole. This is applied dynamically via theuser_has_capfilter (RoleManager::grantStudioCapsToAdministrators()) — it persists nothing and is removed when the plugin is deactivated. Theus_studio_adminrole exists for non-administrator staff who manage the studio.Both grants can be turned off independently on the Access admin page (
AccessSettings, optionsus_admin_grant_studio/us_admin_grant_instructor, both default on) — for example, when dedicatedus_studio_adminorus_instructoraccounts run the studio and administrators should not appear as studio staff. That page is gated on the coremanage_optionscapability (which the plugin never grants or revokes), so an administrator can always reach it to re-enable a grant; disabling one can never lock them out.
Instructor (us_instructor)
Created by the studio admin. Logs in via standard wp-admin. Can:
- Manage their own availability slots (add/delete), including weekly-recurring windows
- Manage their own offerings and intake questions
- View their upcoming confirmed/pending lessons and group enrolments
- View and export their own payments
Capabilities: read, manage_availability, manage_offerings, manage_questions, view_own_lessons, view_own_payments, export_payments
Student (us_student)
Logs in via the front-end [us_student_login] shortcode. Can:
- Browse available lesson slots and offerings from all instructors
- Book a private lesson (single or weekly) and enrol in group classes
Capabilities: read, book_lesson, view_own_lessons
Capability Matrix
| Capability | Studio Admin | Instructor | Student | Used by |
|---|---|---|---|---|
manage_instructors |
✓ | Instructor management | ||
manage_availability |
✓ | Availability | ||
manage_offerings |
✓ | ✓ (own) | Offerings | |
manage_questions |
✓ | ✓ (own) | Registration questions | |
manage_policies |
✓ | Policies | ||
manage_billing |
✓ | Payments (Stripe + overrides) | ||
book_lesson |
✓ | Lesson booking / enrolment | ||
view_all_lessons |
✓ | Scheduler dashboard | ||
view_own_lessons |
✓ | ✓ | Lesson + group views | |
view_own_payments |
✓ | Payment reporting | ||
view_all_payments |
✓ | Payment reporting | ||
export_payments |
✓ | ✓ (own) | Payment reporting export |
Instructor Management
The studio admin gets an Instructors admin page (gated by manage_instructors)
to add an instructor — creating the WP user with the us_instructor role and
emailing them a set-password link — and to toggle that instructor's per-capability
access. The managed capabilities are manage_offerings, manage_questions,
view_own_payments, and export_payments; manage_availability and
view_own_lessons are core to every instructor and are not managed here. The
us_instructor role grants the managed capabilities by default, and the page
stores per-user overrides on top of the role.
A studio admin cannot grant a capability it does not itself hold: only
capabilities the acting user has (checked via current_user_can(), so an
administrator's dynamic grant counts) are offered as toggles, and on creation any
managed capability the admin lacks is denied on the new instructor so they never
exceed the creator. The grantable/assignment rules live in the pure, unit-tested
Auth\InstructorCapabilities; InstructorController applies the result to the
WP_User.
Implementation
- Class:
Unsupervised\Schedular\Auth\RoleManager - Instructor management controller:
Unsupervised\Schedular\Auth\InstructorController - Roles are created on
plugins_loaded → initand on plugin activation viaInstaller. - Permissions are checked with
current_user_can()against the capability string, not the role name.
Tests
tests/Unit/Auth/RoleManagerTest.phptests/Unit/Auth/InstructorCapabilitiesTest.php