PluginProbe
ActivityPub / 9.2.0
ActivityPub v9.2.0
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
activitypub / includes / rest / admin / class-actions-controller.php

class-actions-controller.php in ActivityPub 9.2.0, at includes/rest/admin/class-actions-controller.php

261 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin Actions REST Controller
4 *
5 * Handles administrative actions for followers/actors management.
6 *
7 * @package Activitypub
8 */
9
10 namespace Activitypub\Rest\Admin;
11
12 use Activitypub\Collection\Followers;
13 use Activitypub\Collection\Following;
14 use Activitypub\Collection\Remote_Actors;
15 use Activitypub\Moderation;
16 use Activitypub\OAuth\Server as OAuth_Server;
17
18 use function Activitypub\user_can_activitypub;
19
20 /**
21 * Admin Actions REST Controller Class.
22 */
23 class Actions_Controller extends \WP_REST_Controller {
24 /**
25 * The namespace of this controller's route.
26 *
27 * @var string
28 */
29 protected $namespace = ACTIVITYPUB_REST_NAMESPACE;
30
31 /**
32 * The base of this controller's route.
33 *
34 * @var string
35 */
36 protected $rest_base = 'admin/actors';
37
38 /**
39 * Register routes.
40 */
41 public function register_routes() {
42 // Delete follower relationship.
43 \register_rest_route(
44 $this->namespace,
45 '/' . $this->rest_base . '/(?P<id>[\d]+)/unfollow',
46 array(
47 'args' => array(
48 'id' => array(
49 'description' => 'The ID of the actor.',
50 'type' => 'integer',
51 'required' => true,
52 'validate_callback' => array( $this, 'validate_actor_id' ),
53 ),
54 ),
55 array(
56 'methods' => \WP_REST_Server::DELETABLE,
57 'callback' => array( $this, 'unfollow_actor' ),
58 'permission_callback' => array( $this, 'check_permission' ),
59 'show_in_index' => false,
60 ),
61 )
62 );
63
64 // Block actor.
65 \register_rest_route(
66 $this->namespace,
67 '/' . $this->rest_base . '/(?P<id>[\d]+)/block',
68 array(
69 'args' => array(
70 'id' => array(
71 'description' => 'The ID of the actor.',
72 'type' => 'integer',
73 'required' => true,
74 'validate_callback' => array( $this, 'validate_actor_id' ),
75 ),
76 ),
77 array(
78 'methods' => \WP_REST_Server::CREATABLE,
79 'callback' => array( $this, 'block_actor' ),
80 'permission_callback' => array( $this, 'check_permission' ),
81 'show_in_index' => false,
82 'args' => array(
83 'site_wide' => array(
84 'description' => 'Whether to block site-wide (admin only).',
85 'type' => 'boolean',
86 'default' => false,
87 ),
88 ),
89 ),
90 )
91 );
92
93 // Follow actor.
94 \register_rest_route(
95 $this->namespace,
96 '/' . $this->rest_base . '/(?P<id>[\d]+)/follow',
97 array(
98 'args' => array(
99 'id' => array(
100 'description' => 'The ID of the actor.',
101 'type' => 'integer',
102 'required' => true,
103 'validate_callback' => array( $this, 'validate_actor_id' ),
104 ),
105 ),
106 array(
107 'methods' => \WP_REST_Server::CREATABLE,
108 'callback' => array( $this, 'follow_actor' ),
109 'permission_callback' => array( $this, 'check_permission' ),
110 'show_in_index' => false,
111 ),
112 )
113 );
114 }
115
116 /**
117 * Check if the current user has permission to perform actions.
118 *
119 * @return bool|\WP_Error True if the request has permission, WP_Error object otherwise.
120 */
121 public function check_permission() {
122 // This is an admin endpoint; scoped OAuth C2S tokens must not drive it.
123 $denied = OAuth_Server::deny_if_oauth();
124 if ( null !== $denied ) {
125 return $denied;
126 }
127
128 if ( ! user_can_activitypub( \get_current_user_id() ) ) {
129 return new \WP_Error(
130 'rest_forbidden',
131 \__( 'Sorry, you are not allowed to perform this action.', 'activitypub' ),
132 array( 'status' => 403 )
133 );
134 }
135
136 return true;
137 }
138
139 /**
140 * Validate actor ID.
141 *
142 * @param int $value The actor ID.
143 * @return bool True if valid, false otherwise.
144 */
145 public function validate_actor_id( $value ) {
146 $actor = \get_post( $value );
147
148 return $actor instanceof \WP_Post && Remote_Actors::POST_TYPE === $actor->post_type;
149 }
150
151 /**
152 * Remove follower relationship.
153 *
154 * @param \WP_REST_Request $request Full data about the request.
155 * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure.
156 */
157 public function unfollow_actor( $request ) {
158 $actor_id = $request->get_param( 'id' );
159 $user_id = \get_current_user_id();
160
161 $result = Followers::remove( $actor_id, $user_id );
162
163 if ( ! $result ) {
164 return new \WP_Error(
165 'rest_follower_removal_failed',
166 \__( 'Failed to remove follower.', 'activitypub' ),
167 array( 'status' => 500 )
168 );
169 }
170
171 return new \WP_REST_Response(
172 array(
173 'success' => true,
174 'message' => \__( 'Follower removed successfully.', 'activitypub' ),
175 ),
176 200
177 );
178 }
179
180 /**
181 * Block an actor.
182 *
183 * @param \WP_REST_Request $request Full data about the request.
184 * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure.
185 */
186 public function block_actor( $request ) {
187 $actor_id = $request->get_param( 'id' );
188 $site_wide = $request->get_param( 'site_wide' );
189 $user_id = \get_current_user_id();
190
191 $actor = Remote_Actors::get_actor( $actor_id );
192 if ( \is_wp_error( $actor ) ) {
193 return $actor;
194 }
195
196 $actor_url = $actor->get_id();
197
198 // Add user-specific block.
199 $user_block_success = Moderation::add_user_block( $user_id, 'actor', $actor_url );
200
201 // Add site-wide block if requested and user has permission.
202 $site_block_success = true;
203 if ( $site_wide && \current_user_can( 'manage_options' ) ) {
204 $site_block_success = Moderation::add_site_block( 'actor', $actor_url );
205 }
206
207 if ( ! $user_block_success || ! $site_block_success ) {
208 return new \WP_Error(
209 'rest_actor_block_failed',
210 \__( 'Failed to block actor.', 'activitypub' ),
211 array( 'status' => 500 )
212 );
213 }
214
215 // Remove follower relationship after blocking.
216 Followers::remove( $actor_id, $user_id );
217
218 return new \WP_REST_Response(
219 array(
220 'success' => true,
221 'message' => \__( 'Actor blocked successfully.', 'activitypub' ),
222 ),
223 200
224 );
225 }
226
227 /**
228 * Follow an actor.
229 *
230 * @param \WP_REST_Request $request Full data about the request.
231 * @return \WP_REST_Response|\WP_Error Response object on success, or WP_Error object on failure.
232 */
233 public function follow_actor( $request ) {
234 // Check if following UI is enabled.
235 if ( '1' !== \get_option( 'activitypub_following_ui', '0' ) ) {
236 return new \WP_Error(
237 'rest_following_disabled',
238 \__( 'Following feature is disabled.', 'activitypub' ),
239 array( 'status' => 403 )
240 );
241 }
242
243 $actor_id = $request->get_param( 'id' );
244 $user_id = \get_current_user_id();
245
246 $result = Following::follow( $actor_id, $user_id );
247
248 if ( \is_wp_error( $result ) ) {
249 return $result;
250 }
251
252 return new \WP_REST_Response(
253 array(
254 'success' => true,
255 'message' => \__( 'Actor followed successfully.', 'activitypub' ),
256 ),
257 200
258 );
259 }
260 }
261