PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 0.9.0
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v0.9.0
1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 0.8.8 0.8.7 All 34 releases
desktop-mode / includes / users-window / permissions.php

permissions.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 0.9.0, at includes/users-window/permissions.php

170 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Desktop Mode — Native Users Window: capability gates.
4 *
5 * Multi-tier gating, parallel to WordPress core's `users.php` flow:
6 *
7 * - `list_users` → REGISTER the window. Cap-only check; the
8 * opt-in toggle is JS-side.
9 * - `edit_users` → mutation quick-actions (Send password reset,
10 * Resend welcome).
11 * - `promote_users` → bulk role-change action; per-target gated
12 * through {@see desktop_mode_users_window_assignable_roles()}.
13 * - `create_users` → "Add new user" toolbar button.
14 * - `delete_users` → bulk-delete (single-site).
15 * - `remove_users` → bulk-remove (multisite — removes from current site,
16 * leaves the network user record alone).
17 *
18 * UI-side gating is purely UX polish — the REST routes in `rest.php`
19 * re-validate every cap and every per-target permission before
20 * mutating anything.
21 *
22 * @package WPDesktopMode
23 * @since 0.18.0
24 */
25
26 defined( 'ABSPATH' ) || exit;
27
28 /**
29 * Whether the user is eligible to have the Users window registered.
30 *
31 * @since 0.18.0
32 *
33 * @param int|null $user_id Optional. Defaults to `get_current_user_id()`.
34 * @return bool
35 */
36 function desktop_mode_users_window_user_can_register( $user_id = null ) {
37 $user_id = null === $user_id ? get_current_user_id() : (int) $user_id;
38 $can = $user_id > 0 && user_can( $user_id, 'list_users' );
39
40 /**
41 * Filter whether the current user can have the Users window
42 * registered. This is the boot-time check; runtime "should the
43 * dock click use the native window?" is the JS-side
44 * `nativeUsersEnabled` flag.
45 *
46 * @since 0.18.0
47 *
48 * @param bool $can Default: `list_users` capability.
49 * @param int $user_id User being checked.
50 */
51 return (bool) apply_filters(
52 'desktop_mode_users_window_user_can_register',
53 $can,
54 $user_id
55 );
56 }
57
58 /**
59 * Combined cap-and-opt-in check. Used by callers that want the
60 * combined answer (e.g. analytics, an arrange-menu entry).
61 *
62 * @since 0.18.0
63 *
64 * @param int|null $user_id Optional.
65 * @return bool
66 */
67 function desktop_mode_users_window_user_can_use( $user_id = null ) {
68 $user_id = null === $user_id ? get_current_user_id() : (int) $user_id;
69
70 $cap_ok = desktop_mode_users_window_user_can_register( $user_id );
71
72 $opt_in = false;
73 if ( $cap_ok && function_exists( 'desktop_mode_get_os_settings' ) ) {
74 $settings = desktop_mode_get_os_settings( $user_id );
75 $opt_in = ! empty( $settings['nativeUsersEnabled'] );
76 }
77
78 $can = $cap_ok && $opt_in;
79
80 /**
81 * Filter whether the current user has opted into the native Users
82 * experience.
83 *
84 * @since 0.18.0
85 *
86 * @param bool $can Default gate result.
87 * @param int $user_id User being checked.
88 */
89 return (bool) apply_filters( 'desktop_mode_users_window_user_can_use', $can, $user_id );
90 }
91
92 /**
93 * Resolve the role slugs the current viewer is allowed to assign to
94 * the given target user.
95 *
96 * Honors core's `editable_roles` filter and applies the standard
97 * role-hierarchy rules: a user can only assign roles whose
98 * capabilities are a subset of their own. We compute this server-side
99 * and surface the result on the row so the UI can hide options the
100 * viewer can't apply, but the REST mutation route re-derives the
101 * exact same list and rejects anything outside it.
102 *
103 * @since 0.18.0
104 *
105 * @param int $viewer_id Requesting user.
106 * @param int $target_id Target user (optional — used by filters).
107 * @return string[] Role slugs the viewer can assign to the target.
108 */
109 function desktop_mode_users_window_assignable_roles( $viewer_id, $target_id = 0 ) {
110 $viewer_id = (int) $viewer_id;
111 if ( $viewer_id <= 0 || ! user_can( $viewer_id, 'promote_users' ) ) {
112 return array();
113 }
114
115 // Switch to the viewer's perspective so `current_user_can` and
116 // `get_editable_roles` evaluate against their caps, not whoever
117 // happens to be acting at REST-init time.
118 $prev_user = get_current_user_id();
119 $switched = false;
120 if ( $prev_user !== $viewer_id ) {
121 wp_set_current_user( $viewer_id );
122 $switched = true;
123 }
124
125 // `get_editable_roles()` lives in wp-admin/includes/user.php
126 // which is NOT auto-loaded by the time `init` fires (the hook
127 // our window registers on). Without this require_once the
128 // function doesn't exist, the array comes back empty, and the
129 // admin sees only the site's default_role ("subscriber") in
130 // the role dropdown — exactly the symptom that surfaced once
131 // real-world testing started.
132 if ( ! function_exists( 'get_editable_roles' ) ) {
133 require_once ABSPATH . 'wp-admin/includes/user.php';
134 }
135 $editable = function_exists( 'get_editable_roles' )
136 ? (array) get_editable_roles()
137 : array();
138
139 if ( $switched ) {
140 wp_set_current_user( $prev_user );
141 }
142
143 $slugs = array_keys( $editable );
144
145 /**
146 * Filter the role slugs assignable by `$viewer_id` to `$target_id`.
147 *
148 * Use this to LOCK DOWN role assignment further (e.g. "site
149 * managers can't promote anyone to administrator even if core
150 * would let them"). Returning an empty array fully disables role
151 * mutation for the viewer.
152 *
153 * Returning a SUPERSET of the default has no effect on the REST
154 * endpoint — that re-derives `get_editable_roles()` itself, this
155 * filter only widens / narrows what the UI surfaces.
156 *
157 * @since 0.18.0
158 *
159 * @param string[] $slugs Default role slug list.
160 * @param int $viewer_id
161 * @param int $target_id
162 */
163 return (array) apply_filters(
164 'desktop_mode_users_window_assignable_roles',
165 $slugs,
166 $viewer_id,
167 $target_id
168 );
169 }
170