PluginProbe
ActivityPub / 3.2.3
ActivityPub v3.2.3
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 / collection / class-users.php

class-users.php in ActivityPub 3.2.3, at includes/collection/class-users.php

279 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Activitypub\Collection;
3
4 use WP_Error;
5 use WP_User_Query;
6 use Activitypub\Model\User;
7 use Activitypub\Model\Blog;
8 use Activitypub\Model\Application;
9
10 use function Activitypub\object_to_uri;
11 use function Activitypub\normalize_url;
12 use function Activitypub\normalize_host;
13 use function Activitypub\url_to_authorid;
14 use function Activitypub\is_user_disabled;
15
16 class Users {
17 /**
18 * The ID of the Blog User
19 *
20 * @var int
21 */
22 const BLOG_USER_ID = 0;
23
24 /**
25 * The ID of the Application User
26 *
27 * @var int
28 */
29 const APPLICATION_USER_ID = -1;
30
31 /**
32 * Get the User by ID
33 *
34 * @param int $user_id The User-ID.
35 *
36 * @return \Acitvitypub\Model\User The User.
37 */
38 public static function get_by_id( $user_id ) {
39 if ( is_string( $user_id ) || is_numeric( $user_id ) ) {
40 $user_id = (int) $user_id;
41 }
42
43 if ( is_user_disabled( $user_id ) ) {
44 return new WP_Error(
45 'activitypub_user_not_found',
46 \__( 'User not found', 'activitypub' ),
47 array( 'status' => 404 )
48 );
49 }
50
51 if ( self::BLOG_USER_ID === $user_id ) {
52 return new Blog();
53 } elseif ( self::APPLICATION_USER_ID === $user_id ) {
54 return new Application();
55 } elseif ( $user_id > 0 ) {
56 return User::from_wp_user( $user_id );
57 }
58
59 return new WP_Error(
60 'activitypub_user_not_found',
61 \__( 'User not found', 'activitypub' ),
62 array( 'status' => 404 )
63 );
64 }
65
66 /**
67 * Get the User by username.
68 *
69 * @param string $username The User-Name.
70 *
71 * @return \Acitvitypub\Model\User The User.
72 */
73 public static function get_by_username( $username ) {
74 // check for blog user.
75 if ( Blog::get_default_username() === $username ) {
76 return new Blog();
77 }
78
79 if ( get_option( 'activitypub_blog_identifier' ) === $username ) {
80 return new Blog();
81 }
82
83 // check for application user.
84 if ( 'application' === $username ) {
85 return new Application();
86 }
87
88 // check for 'activitypub_username' meta
89 $user = new WP_User_Query(
90 array(
91 'count_total' => false,
92 'number' => 1,
93 'hide_empty' => true,
94 'fields' => 'ID',
95 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
96 'meta_query' => array(
97 'relation' => 'OR',
98 array(
99 'key' => 'activitypub_user_identifier',
100 'value' => $username,
101 'compare' => 'LIKE',
102 ),
103 ),
104 )
105 );
106
107 if ( $user->results ) {
108 return self::get_by_id( $user->results[0] );
109 }
110
111 $username = str_replace( array( '*', '%' ), '', $username );
112
113 // check for login or nicename.
114 $user = new WP_User_Query(
115 array(
116 'count_total' => false,
117 'search' => $username,
118 'search_columns' => array( 'user_login', 'user_nicename' ),
119 'number' => 1,
120 'hide_empty' => true,
121 'fields' => 'ID',
122 )
123 );
124
125 if ( $user->results ) {
126 return self::get_by_id( $user->results[0] );
127 }
128
129 return new WP_Error(
130 'activitypub_user_not_found',
131 \__( 'User not found', 'activitypub' ),
132 array( 'status' => 404 )
133 );
134 }
135
136 /**
137 * Get the User by resource.
138 *
139 * @param string $resource The User-Resource.
140 *
141 * @return \Acitvitypub\Model\User The User.
142 */
143 public static function get_by_resource( $resource ) {
144 $resource = object_to_uri( $resource );
145
146 $scheme = 'acct';
147 $match = array();
148 // try to extract the scheme and the host
149 if ( preg_match( '/^([a-zA-Z^:]+):(.*)$/i', $resource, $match ) ) {
150 // extract the scheme
151 $scheme = \esc_attr( $match[1] );
152 }
153
154 switch ( $scheme ) {
155 // check for http(s) URIs
156 case 'http':
157 case 'https':
158 $resource_path = \wp_parse_url( $resource, PHP_URL_PATH );
159
160 if ( $resource_path ) {
161 $blog_path = \wp_parse_url( \home_url(), PHP_URL_PATH );
162
163 if ( $blog_path ) {
164 $resource_path = \str_replace( $blog_path, '', $resource_path );
165 }
166
167 $resource_path = \trim( $resource_path, '/' );
168
169 // check for http(s)://blog.example.com/@username
170 if ( str_starts_with( $resource_path, '@' ) ) {
171 $identifier = \str_replace( '@', '', $resource_path );
172 $identifier = \trim( $identifier, '/' );
173
174 return self::get_by_username( $identifier );
175 }
176 }
177
178 // check for http(s)://blog.example.com/author/username
179 $user_id = url_to_authorid( $resource );
180
181 if ( $user_id ) {
182 return self::get_by_id( $user_id );
183 }
184
185 // check for http(s)://blog.example.com/
186 if (
187 normalize_url( site_url() ) === normalize_url( $resource ) ||
188 normalize_url( home_url() ) === normalize_url( $resource )
189 ) {
190 return self::get_by_id( self::BLOG_USER_ID );
191 }
192
193 return new WP_Error(
194 'activitypub_no_user_found',
195 \__( 'User not found', 'activitypub' ),
196 array( 'status' => 404 )
197 );
198 // check for acct URIs
199 case 'acct':
200 $resource = \str_replace( 'acct:', '', $resource );
201 $identifier = \substr( $resource, 0, \strrpos( $resource, '@' ) );
202 $host = normalize_host( \substr( \strrchr( $resource, '@' ), 1 ) );
203 $blog_host = normalize_host( \wp_parse_url( \home_url( '/' ), \PHP_URL_HOST ) );
204
205 if ( $blog_host !== $host ) {
206 return new WP_Error(
207 'activitypub_wrong_host',
208 \__( 'Resource host does not match blog host', 'activitypub' ),
209 array( 'status' => 404 )
210 );
211 }
212
213 // prepare wildcards https://github.com/mastodon/mastodon/issues/22213
214 if ( in_array( $identifier, array( '_', '*', '' ), true ) ) {
215 return self::get_by_id( self::BLOG_USER_ID );
216 }
217
218 return self::get_by_username( $identifier );
219 default:
220 return new WP_Error(
221 'activitypub_wrong_scheme',
222 \__( 'Wrong scheme', 'activitypub' ),
223 array( 'status' => 404 )
224 );
225 }
226 }
227
228 /**
229 * Get the User by resource.
230 *
231 * @param string $resource The User-Resource.
232 *
233 * @return \Acitvitypub\Model\User The User.
234 */
235 public static function get_by_various( $id ) {
236 $user = null;
237
238 if ( is_numeric( $id ) ) {
239 $user = self::get_by_id( $id );
240 } elseif (
241 // is URL
242 filter_var( $id, FILTER_VALIDATE_URL ) ||
243 // is acct
244 str_starts_with( $id, 'acct:' ) ||
245 // is email
246 filter_var( $id, FILTER_VALIDATE_EMAIL )
247 ) {
248 $user = self::get_by_resource( $id );
249 }
250
251 if ( $user && ! is_wp_error( $user ) ) {
252 return $user;
253 }
254
255 return self::get_by_username( $id );
256 }
257
258 /**
259 * Get the User collection.
260 *
261 * @return array The User collection.
262 */
263 public static function get_collection() {
264 $users = \get_users(
265 array(
266 'capability__in' => array( 'activitypub' ),
267 )
268 );
269
270 $return = array();
271
272 foreach ( $users as $user ) {
273 $return[] = User::from_wp_user( $user->ID );
274 }
275
276 return $return;
277 }
278 }
279