67f8144a4a
CI / No Debug Code (pull_request) Successful in 3s
CI / Tests (PHP 8.2) (pull_request) Successful in 41s
CI / Tests (PHP 8.3) (pull_request) Successful in 51s
CI / Tests (PHP 8.1) (pull_request) Successful in 54s
CI / Coding Standards (pull_request) Successful in 58s
CI / PHPStan (pull_request) Successful in 1m9s
CI / Build Plugin Zip (pull_request) Has been skipped
A WordPress administrator previously inherited the studio-admin capabilities but not `manage_availability`, so the studio owner running as an admin had no way to reach "My Availability" or act as the instructor — breaking single-instructor businesses. Grant the instructor capabilities to administrators as well (via the existing `user_has_cap` filter), and make both grants — studio-admin and instructor — independently toggleable from a new Access admin page. - RoleManager: extract `INSTRUCTOR_CAPS`; apply studio and instructor cap sets to administrators, each gated on a stored toggle (default on). - AccessSettings + templates/admin/access.php: two options (`us_admin_grant_studio` / `us_admin_grant_instructor`), gated on the core `manage_options` capability so disabling a grant can never lock an administrator out of re-enabling it. - AdminMenu: register the Access page after Studio Settings; keep the studio sidebar separator visible for any administrator. - Tests for the toggles and the new settings reader; docs updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
85 lines
5.0 KiB
Markdown
85 lines
5.0 KiB
Markdown
# 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** (notably
|
|
> `manage_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 the `us_studio_admin` or `us_instructor` role. This is
|
|
> applied dynamically via the `user_has_cap` filter
|
|
> (`RoleManager::grantStudioCapsToAdministrators()`) — it persists nothing and is
|
|
> removed when the plugin is deactivated. The `us_studio_admin` role exists for
|
|
> non-administrator staff who manage the studio.
|
|
>
|
|
> Both grants can be turned off independently on the **Access** admin page
|
|
> (`AccessSettings`, options `us_admin_grant_studio` / `us_admin_grant_instructor`,
|
|
> both default on) — for example, when dedicated `us_studio_admin` or
|
|
> `us_instructor` accounts run the studio and administrators should not appear as
|
|
> studio staff. That page is gated on the core `manage_options` capability (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 to
|
|
toggle that instructor's per-capability access (e.g. whether they may manage their
|
|
own offerings/questions or export payments). The studio admin cannot grant a
|
|
capability it does not itself hold.
|
|
|
|
## Implementation
|
|
- Class: `Unsupervised\Schedular\Auth\RoleManager`
|
|
- Instructor management controller: `Unsupervised\Schedular\Auth\InstructorController`
|
|
- Roles are created on `plugins_loaded → init` and on plugin activation via `Installer`.
|
|
- Permissions are checked with `current_user_can()` against the capability string, not the role name.
|
|
|
|
## Tests
|
|
- `tests/Unit/Auth/RoleManagerTest.php`
|
|
- `tests/Unit/Auth/InstructorControllerTest.php`
|