PluginProbe
WP Approve User / 13
WP Approve User v13
13 12 trunk 1.0 1.1.0 1.1.1 10 11 2.0.0 2.1.0 2.1.1 2.2.0 2.2.1 2.2.2 2.2.3 2.4.0 3 4 5 6 7 8 9
wp-approve-user / abilities.php

abilities.php in WP Approve User 13, at abilities.php

231 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WordPress Abilities API integration.
4 *
5 * Registers `wp-approve-user/approve` and `wp-approve-user/unapprove` abilities
6 * so third parties (plugins, agents, REST clients) can flip a user's approval
7 * state through the core Abilities API shipped in WordPress 6.9.
8 *
9 * See https://developer.wordpress.org/news/2025/11/introducing-the-wordpress-abilities-api/
10 *
11 * @package WP Approve User
12 */
13
14 /**
15 * Registers the category the approve/unapprove abilities live under.
16 *
17 * @since 13
18 */
19 function wpau_register_ability_categories() {
20 wp_register_ability_category(
21 'user-management',
22 array(
23 'label' => 'User management',
24 'description' => 'Abilities for managing users and their access.',
25 )
26 );
27 }
28 add_action( 'wp_abilities_api_categories_init', 'wpau_register_ability_categories' );
29
30 /**
31 * Registers the approve/unapprove abilities with the core registry.
32 *
33 * @since 13
34 */
35 function wpau_register_abilities() {
36 $input_schema = array(
37 'type' => 'object',
38 'properties' => array(
39 'user_id' => array(
40 'type' => 'integer',
41 'description' => 'The ID of the user to update.',
42 'minimum' => 1,
43 ),
44 ),
45 'required' => array( 'user_id' ),
46 );
47
48 $output_schema = array(
49 'type' => 'object',
50 'properties' => array(
51 'success' => array(
52 'type' => 'boolean',
53 'description' => 'Whether the operation completed successfully.',
54 ),
55 'user_id' => array(
56 'type' => 'integer',
57 'description' => 'The ID of the user that was updated.',
58 ),
59 'status' => array(
60 'type' => 'string',
61 'description' => 'The resulting approval status for the user.',
62 'enum' => array( 'approved', 'unapproved', 'pending' ),
63 ),
64 ),
65 'required' => array( 'success', 'user_id', 'status' ),
66 );
67
68 wp_register_ability(
69 'wp-approve-user/approve',
70 array(
71 'label' => 'Approve user',
72 'description' => 'Marks a user as approved so they can log in to the site.',
73 'category' => 'user-management',
74 'input_schema' => $input_schema,
75 'output_schema' => $output_schema,
76 'permission_callback' => 'wpau_ability_permission_callback',
77 'execute_callback' => 'wpau_ability_approve_callback',
78 'meta' => array(
79 'show_in_rest' => true,
80 ),
81 )
82 );
83
84 wp_register_ability(
85 'wp-approve-user/unapprove',
86 array(
87 'label' => 'Unapprove user',
88 'description' => 'Marks a user as unapproved so they can no longer log in to the site.',
89 'category' => 'user-management',
90 'input_schema' => $input_schema,
91 'output_schema' => $output_schema,
92 'permission_callback' => 'wpau_ability_permission_callback',
93 'execute_callback' => 'wpau_ability_unapprove_callback',
94 'meta' => array(
95 'show_in_rest' => true,
96 ),
97 )
98 );
99 }
100 add_action( 'wp_abilities_api_init', 'wpau_register_abilities' );
101
102 /**
103 * Permission callback shared by both approve/unapprove abilities.
104 *
105 * @since 13
106 *
107 * @param array $input Input arguments validated against the input schema.
108 * @return true|WP_Error True when the current user may promote and edit the target user, WP_Error otherwise.
109 */
110 function wpau_ability_permission_callback( $input = array() ) {
111 if ( ! current_user_can( 'promote_users' ) ) {
112 return new WP_Error(
113 'wpau_rest_forbidden',
114 __( 'Sorry, you are not allowed to change user approval status.', 'wp-approve-user' ),
115 array( 'status' => rest_authorization_required_code() )
116 );
117 }
118
119 $user_id = isset( $input['user_id'] ) ? (int) $input['user_id'] : 0;
120
121 if ( $user_id > 0 && ! current_user_can( 'edit_user', $user_id ) ) {
122 return new WP_Error(
123 'wpau_rest_forbidden',
124 __( 'Sorry, you are not allowed to edit this user.', 'wp-approve-user' ),
125 array( 'status' => rest_authorization_required_code() )
126 );
127 }
128
129 return true;
130 }
131
132 /**
133 * Execute callback for the approve ability.
134 *
135 * Updates the three-state meta to `approved` and fires the `wpau_approve`
136 * action so existing side-effects (approval email, logging, etc.) still run.
137 *
138 * @since 13
139 *
140 * @param array $input Input arguments validated against the input schema.
141 * @return array|WP_Error Result payload or a WP_Error on failure.
142 */
143 function wpau_ability_approve_callback( $input ) {
144 $user_id = isset( $input['user_id'] ) ? (int) $input['user_id'] : 0;
145
146 $userdata = $user_id > 0 ? get_userdata( $user_id ) : false;
147
148 if ( ! $userdata ) {
149 return new WP_Error(
150 'wpau_invalid_user',
151 __( 'The specified user does not exist.', 'wp-approve-user' ),
152 array( 'status' => 404 )
153 );
154 }
155
156 $admin_user = get_user_by( 'email', get_bloginfo( 'admin_email' ) );
157 if ( $admin_user && (int) $admin_user->ID === $user_id ) {
158 return new WP_Error(
159 'wpau_cannot_edit_admin_email',
160 __( 'The site admin email user cannot be modified through this ability.', 'wp-approve-user' ),
161 array( 'status' => 403 )
162 );
163 }
164
165 update_user_meta( $user_id, 'wp-approve-user', 'approved' );
166 $status = get_user_meta( $user_id, 'wp-approve-user', true );
167
168 /** This action is documented in class-obenland-wp-approve-user.php */
169 do_action( 'wpau_approve', $user_id );
170
171 return array(
172 'success' => 'approved' === $status,
173 'user_id' => $user_id,
174 'status' => $status,
175 );
176 }
177
178 /**
179 * Execute callback for the unapprove ability.
180 *
181 * Updates the three-state meta to `unapproved` and fires the `wpau_unapprove`
182 * action so existing side-effects (rejection email, logging, etc.) still run.
183 *
184 * @since 13
185 *
186 * @param array $input Input arguments validated against the input schema.
187 * @return array|WP_Error Result payload or a WP_Error on failure.
188 */
189 function wpau_ability_unapprove_callback( $input ) {
190 $user_id = isset( $input['user_id'] ) ? (int) $input['user_id'] : 0;
191
192 $userdata = $user_id > 0 ? get_userdata( $user_id ) : false;
193
194 if ( ! $userdata ) {
195 return new WP_Error(
196 'wpau_invalid_user',
197 __( 'The specified user does not exist.', 'wp-approve-user' ),
198 array( 'status' => 404 )
199 );
200 }
201
202 $admin_user = get_user_by( 'email', get_bloginfo( 'admin_email' ) );
203 if ( $admin_user && (int) $admin_user->ID === $user_id ) {
204 return new WP_Error(
205 'wpau_cannot_edit_admin_email',
206 __( 'The site admin email user cannot be modified through this ability.', 'wp-approve-user' ),
207 array( 'status' => 403 )
208 );
209 }
210
211 update_user_meta( $user_id, 'wp-approve-user', 'unapproved' );
212 $status = get_user_meta( $user_id, 'wp-approve-user', true );
213
214 /*
215 * Mirror the admin UI's unapprove() behaviour — destroy all active sessions for the
216 * user so that an unapproved user can no longer hit wp-admin with an existing cookie.
217 */
218 if ( class_exists( 'WP_Session_Tokens' ) ) {
219 WP_Session_Tokens::get_instance( $user_id )->destroy_all();
220 }
221
222 /** This action is documented in class-obenland-wp-approve-user.php */
223 do_action( 'wpau_unapprove', $user_id );
224
225 return array(
226 'success' => 'unapproved' === $status,
227 'user_id' => $user_id,
228 'status' => $status,
229 );
230 }
231