# 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`