Grant studio-admin capabilities to WordPress administrators
WordPress administrators (manage_options) now implicitly hold every studio-admin capability via a user_has_cap filter, so the site owner runs the studio without being assigned the separate us_studio_admin role. The grant persists nothing and is removed on deactivation. The us_studio_admin role still exists for non-administrator staff and does NOT confer any core WordPress admin powers. Also re-gate the studio-wide "Scheduler" dashboard off manage_options onto a new view_all_lessons capability (added to the studio-admin cap set), so a us_studio_admin user can see it too — previously it was administrator-only. - RoleManager: STUDIO_ADMIN_CAPS constant, CAP_VIEW_ALL_LESSONS, grantStudioCapsToAdministrators() user_has_cap filter - AdminMenu + LessonController: Scheduler gated on view_all_lessons - Docs: user-roles.md cap matrix + administrator note; lesson-booking.md - Tests: administrators receive studio caps; non-admins do not Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+2
-2
@@ -32,11 +32,11 @@ class AdminMenu {
|
||||
}
|
||||
|
||||
public function addPages(): void {
|
||||
// Admin-only dashboard: all upcoming lessons.
|
||||
// Studio-wide dashboard: all upcoming lessons across instructors.
|
||||
add_menu_page(
|
||||
__( 'Scheduler', 'unsupervised-schedular' ),
|
||||
__( 'Scheduler', 'unsupervised-schedular' ),
|
||||
'manage_options',
|
||||
RoleManager::CAP_VIEW_ALL_LESSONS,
|
||||
'us-scheduler',
|
||||
[ $this->lessonController, 'renderAdminDashboard' ],
|
||||
'dashicons-calendar-alt',
|
||||
|
||||
+49
-10
@@ -18,29 +18,44 @@ class RoleManager {
|
||||
public const CAP_MANAGE_QUESTIONS = 'manage_questions';
|
||||
public const CAP_MANAGE_POLICIES = 'manage_policies';
|
||||
public const CAP_MANAGE_BILLING = 'manage_billing';
|
||||
public const CAP_VIEW_ALL_LESSONS = 'view_all_lessons';
|
||||
public const CAP_VIEW_ALL_PAYMENTS = 'view_all_payments';
|
||||
public const CAP_VIEW_OWN_PAYMENTS = 'view_own_payments';
|
||||
public const CAP_EXPORT_PAYMENTS = 'export_payments';
|
||||
|
||||
/**
|
||||
* Capabilities granted to the `us_studio_admin` role, and implicitly to any
|
||||
* WordPress administrator (see {@see grantStudioCapsToAdministrators()}).
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
public const STUDIO_ADMIN_CAPS = [
|
||||
self::CAP_MANAGE_INSTRUCTORS,
|
||||
self::CAP_MANAGE_OFFERINGS,
|
||||
self::CAP_MANAGE_QUESTIONS,
|
||||
self::CAP_MANAGE_POLICIES,
|
||||
self::CAP_MANAGE_BILLING,
|
||||
self::CAP_VIEW_ALL_LESSONS,
|
||||
self::CAP_VIEW_ALL_PAYMENTS,
|
||||
self::CAP_EXPORT_PAYMENTS,
|
||||
];
|
||||
|
||||
public function register(): void {
|
||||
add_action( 'init', [ $this, 'createRoles' ] );
|
||||
add_filter( 'user_has_cap', [ $this, 'grantStudioCapsToAdministrators' ], 10, 1 );
|
||||
}
|
||||
|
||||
public function createRoles(): void {
|
||||
if ( get_role( self::STUDIO_ADMIN ) === null ) {
|
||||
$studioCaps = [ 'read' => true ];
|
||||
foreach ( self::STUDIO_ADMIN_CAPS as $cap ) {
|
||||
$studioCaps[ $cap ] = true;
|
||||
}
|
||||
|
||||
add_role(
|
||||
self::STUDIO_ADMIN,
|
||||
__( 'Studio Admin', 'unsupervised-schedular' ),
|
||||
[
|
||||
'read' => true,
|
||||
self::CAP_MANAGE_INSTRUCTORS => true,
|
||||
self::CAP_MANAGE_OFFERINGS => true,
|
||||
self::CAP_MANAGE_QUESTIONS => true,
|
||||
self::CAP_MANAGE_POLICIES => true,
|
||||
self::CAP_MANAGE_BILLING => true,
|
||||
self::CAP_VIEW_ALL_PAYMENTS => true,
|
||||
self::CAP_EXPORT_PAYMENTS => true,
|
||||
]
|
||||
$studioCaps
|
||||
);
|
||||
}
|
||||
|
||||
@@ -72,4 +87,28 @@ class RoleManager {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant every studio-admin capability to WordPress administrators.
|
||||
*
|
||||
* The studio owner runs the site as an administrator (`manage_options`) and
|
||||
* should manage offerings, questions, policies, billing, and reports without
|
||||
* being assigned the separate `us_studio_admin` role. Applied dynamically via
|
||||
* the `user_has_cap` filter, so nothing is persisted and the grant disappears
|
||||
* when the plugin is deactivated.
|
||||
*
|
||||
* @param array<string, bool> $allcaps All capabilities currently held by the user.
|
||||
* @return array<string, bool>
|
||||
*/
|
||||
public function grantStudioCapsToAdministrators( array $allcaps ): array {
|
||||
if ( empty( $allcaps['manage_options'] ) ) {
|
||||
return $allcaps;
|
||||
}
|
||||
|
||||
foreach ( self::STUDIO_ADMIN_CAPS as $cap ) {
|
||||
$allcaps[ $cap ] = true;
|
||||
}
|
||||
|
||||
return $allcaps;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class LessonController {
|
||||
public function __construct( private BookingRepository $repository ) {}
|
||||
|
||||
public function renderAdminDashboard(): void {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
if ( ! current_user_can( RoleManager::CAP_VIEW_ALL_LESSONS ) ) {
|
||||
wp_die( esc_html__( 'You do not have permission to view this page.', 'unsupervised-schedular' ) );
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user