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 +125 -16 1.40 → 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
@@ -246,9 +313,9 @@
246 313 }
247 314
248 315 /**
249 316 * Get array of board Ids for logged-in user
250 - * @param null $userId
317 + * @param int $userId
251 318 * @return array
252 319 */
253 320 public static function getBoardIdsForUser($userId = null, $boardId = null)
254 321 {
@@ -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
@@ -368,6 +441,42 @@
368 441 }
369 442
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);
445 + }
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 + */
451 + public static function userHasBoardCreationPermission($userId = null)
452 + {
453 + if (!$userId) {
454 + $userId = get_current_user_id();
455 + if (!$userId) {
456 + return false;
457 + }
458 + }
459 +
460 + if (static::isAdmin($userId)) {
461 + return apply_filters('fluent_boards/can_create_board', true, $userId);
462 + }
463 +
464 + // Check if "allow members to create boards" setting is enabled
465 + $generalSettings = fluent_boards_get_option('general_settings', []);
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 + }
478 + }
479 +
480 + return apply_filters('fluent_boards/can_create_board', false, $userId);
372 481 }
373 482 }