PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.2.0
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.2.0
2.2.0 2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 All 43 releases
← All changes | app/Services/PermissionManager.php +104 -17 1.95.3 → 2.2.0 View file →
@@ -106,9 +106,9 @@
106 106 if (!$boardUser) {
107 107 return false;
108 108 }
109 109
110 - return (bool)$boardUser->settings ? $boardUser->settings['is_admin'] : null;
110 + return (bool)($boardUser->settings[Constant::IS_BOARD_ADMIN] ?? false);
111 111
112 112 }
113 113
114 114 public static function userHasAnyBoardAccess($userId = null): bool
@@ -156,8 +156,38 @@
156 156 ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
157 157 ->exists();
158 158 }
159 159
160 + /** Filter existing users by board membership or global admin access using bulk lookups. */
161 + public static function getUserIdsWithBoardAccess($boardId, array $userIds): array
162 + {
163 + $boardId = absint($boardId);
164 + $userIds = array_values(array_unique(array_filter(array_map('absint', $userIds))));
165 + if (!$boardId || !$userIds) {
166 + return [];
167 + }
168 +
169 + $memberIds = Relation::where('object_id', $boardId)
170 + ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
171 + ->whereIn('foreign_id', $userIds)
172 + ->pluck('foreign_id')->toArray();
173 + $adminIds = Meta::where('object_type', Constant::FLUENT_BOARD_ADMIN)
174 + ->whereIn('object_id', $userIds)
175 + ->pluck('object_id')->toArray();
176 + $allowedIds = array_fill_keys(array_merge($memberIds, $adminIds), true);
177 +
178 + // Loading full users primes their metadata together before capability checks.
179 + $users = get_users(['include' => $userIds, 'fields' => 'all']);
180 + $accessibleIds = [];
181 + foreach ($users as $user) {
182 + if (isset($allowedIds[$user->ID]) || user_can($user, 'manage_options')) {
183 + $accessibleIds[] = (int) $user->ID;
184 + }
185 + }
186 +
187 + return array_values(array_intersect($userIds, $accessibleIds));
188 + }
189 +
160 190 public static function isFluentBoardsAdmin($userId = null): bool
161 191 {
162 192 if (!$userId) {
163 193 $userId = get_current_user_id();
@@ -200,14 +230,62 @@
200 230
201 231 return true;
202 232 }
203 233
234 + public static function userCanAccessMemberProfile($targetUserId, $userId = null): bool
235 + {
236 + $targetUserId = intval($targetUserId);
237 +
238 + if (!$userId) {
239 + $userId = get_current_user_id();
240 + }
241 +
242 + $userId = intval($userId);
243 +
244 + if (!$targetUserId || !$userId) {
245 + return false;
246 + }
247 +
248 + if ($userId === $targetUserId || static::isAdmin($userId)) {
249 + return true;
250 + }
251 +
252 + if (!static::isFluentBoardsUser($targetUserId)) {
253 + return false;
254 + }
255 +
256 + $boardIds = Relation::where('foreign_id', $userId)
257 + ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
258 + ->pluck('object_id')
259 + ->toArray();
260 +
261 + if (empty($boardIds)) {
262 + return false;
263 + }
264 +
265 + return Relation::where('foreign_id', $targetUserId)
266 + ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
267 + ->whereIn('object_id', $boardIds)
268 + ->exists();
269 + }
270 +
271 + /**
272 + * Check WordPress or Boards admin access, caching by the resolved user ID.
273 + */
204 274 public static function isAdmin($userId = null, $useCache = true)
205 275 {
206 276
207 277 static $cache = [];
208 278
209 - if (isset($cache[$userId]) && $useCache) {
279 + if (!$userId) {
280 + $userId = get_current_user_id();
281 + }
282 +
283 + if (!$userId) {
284 + return false;
285 + }
286 +
287 + if ($useCache && isset($cache[$userId])) {
210 288 return $cache[$userId];
211 289 }
212 290
213 291 /*
@@ -217,19 +295,8 @@
217 295 * if user is WordPress admin then we will allow him
218 296 * if user is FluentBoard admin then we will allow him
219 297 */
220 298
221 - if (!$userId) {
222 - $userId = get_current_user_id();
223 - if (!$userId) {
224 - return false;
225 - }
226 - }
227 -
228 - if (!$userId) {
229 - return false;
230 - }
231 -
232 299 if (user_can($userId, 'manage_options')) { // WordPress Administrator
233 300
234 301 $cache[$userId] = true;
235 302
@@ -307,9 +374,9 @@
307 374 {
308 375 return !!is_user_logged_in();
309 376 }
310 377
311 - public static function getAll_WP_Admins($searchquery = '')
378 + public static function getAll_WP_Admins($searchquery = '', $number = null)
312 379 {
313 380 $args = array(
314 381 'role' => '',
315 382 'capability' => 'manage_options',
@@ -315,8 +382,14 @@
315 382 'capability' => 'manage_options',
316 383 'search' => '*' . $searchquery . '*',
317 384 );
318 385
386 + // Optionally bound the result set (e.g. for selector popovers) so an
387 + // empty search can't serialize every admin-capable user on large sites.
388 + if ($number !== null) {
389 + $args['number'] = (int) $number;
390 + }
391 +
319 392 return get_users($args);
320 393 }
321 394
322 395 public static function isWPAdmin($userId = null)
@@ -346,9 +419,9 @@
346 419 return false; // Return false if no board ID is provided
347 420 }
348 421
349 422 // Admins have full permissions, allow access immediately
350 - if (static::isAdmin()) {
423 + if (static::isAdmin($userId)) {
351 424 return true;
352 425 }
353 426
354 427 // Fetch user permissions for the given board
@@ -370,8 +443,12 @@
370 443 // Deny access if the user is a viewer only and trying to modify data
371 444 return !($boardPermissions->settings['is_viewer_only'] ?? false);
372 445 }
373 446
447 + /**
448 + * Allow admins, or members with a non-viewer membership when creation is enabled.
449 + * The final filter remains available for site-specific permission overrides.
450 + */
374 451 public static function userHasBoardCreationPermission($userId = null)
375 452 {
376 453 if (!$userId) {
377 454 $userId = get_current_user_id();
@@ -385,10 +462,20 @@
385 462 }
386 463
387 464 // Check if "allow members to create boards" setting is enabled
388 465 $generalSettings = fluent_boards_get_option('general_settings', []);
389 - if (!empty($generalSettings['allow_members_to_create_boards']) && $generalSettings['allow_members_to_create_boards'] !== 'false' && static::userHasAnyBoardAccess($userId)) {
390 - return apply_filters('fluent_boards/can_create_board', true, $userId);
466 + if (!empty($generalSettings['allow_members_to_create_boards']) && $generalSettings['allow_members_to_create_boards'] !== 'false') {
467 + $memberships = Relation::where('foreign_id', $userId)
468 + ->where('object_type', Constant::OBJECT_TYPE_BOARD_USER)
469 + ->whereNotNull('object_id')
470 + ->get(['settings']);
471 +
472 + // Roles are per board: a viewer elsewhere may still be a member or manager here.
473 + foreach ($memberships as $membership) {
474 + if (!($membership->settings['is_viewer_only'] ?? false)) {
475 + return apply_filters('fluent_boards/can_create_board', true, $userId);
476 + }
477 + }
391 478 }
392 479
393 480 return apply_filters('fluent_boards/can_create_board', false, $userId);
394 481 }