$_) { $folders[$name] = true; } } } } $folderList = array_keys($folders); if (!in_array('root', $folderList, true)) { array_unshift($folderList, 'root'); } $has = function(array $arr, string $u): bool { foreach ($arr as $x) { if (strcasecmp((string)$x, $u) === 0) return true; } return false; }; $out = []; foreach ($folderList as $f) { $rec = ACL::explicitAll($f); $isOwner = $has($rec['owners'], $user); $canViewAll = $isOwner || $has($rec['read'], $user); $canViewOwn = $has($rec['read_own'], $user); $canShare = $isOwner || $has($rec['share'], $user); $canUpload = $isOwner || $has($rec['write'], $user) || $has($rec['upload'], $user); if ( $canViewAll || $canViewOwn || $canUpload || $canShare || $isOwner || $has($rec['create'], $user) || $has($rec['edit'], $user) || $has($rec['rename'], $user) || $has($rec['copy'], $user) || $has($rec['move'], $user) || $has($rec['delete'], $user) || $has($rec['extract'], $user) || $has($rec['share_file'], $user) || $has($rec['share_folder'], $user) ) { $out[$f] = [ 'view' => $canViewAll, 'viewOwn' => $canViewOwn, 'write' => $has($rec['write'], $user) || $isOwner, 'manage' => $isOwner, 'share' => $canShare, 'create' => $isOwner || $has($rec['create'], $user), 'upload' => $isOwner || $has($rec['upload'], $user) || $has($rec['write'], $user), 'edit' => $isOwner || $has($rec['edit'], $user) || $has($rec['write'], $user), 'rename' => $isOwner || $has($rec['rename'], $user) || $has($rec['write'], $user), 'copy' => $isOwner || $has($rec['copy'], $user) || $has($rec['write'], $user), 'move' => $isOwner || $has($rec['move'], $user) || $has($rec['write'], $user), 'delete' => $isOwner || $has($rec['delete'], $user) || $has($rec['write'], $user), 'extract' => $isOwner || $has($rec['extract'], $user)|| $has($rec['write'], $user), 'shareFile' => $isOwner || $has($rec['share_file'], $user) || $has($rec['share'], $user), 'shareFolder' => $isOwner || $has($rec['share_folder'], $user) || $has($rec['share'], $user), ]; } } return $out; } public function saveUserGrantsPayload(array $payload): array { $normalizeCaps = function (array $row): array { $bool = function ($v) { return !empty($v) && $v !== 'false' && $v !== 0; }; $k = [ 'view','viewOwn','upload','manage','share', 'create','edit','rename','copy','move','delete','extract', 'shareFile','shareFolder','write' ]; $out = []; foreach ($k as $kk) { $out[$kk] = $bool($row[$kk] ?? false); } if ($out['shareFolder'] && !$out['view']) { $out['view'] = true; } if ($out['shareFile'] && !$out['view'] && !$out['viewOwn']) { $out['viewOwn'] = true; } return $out; }; $sanitizeGrantsMap = function (array $grants) use ($normalizeCaps): array { $out = []; foreach ($grants as $folder => $caps) { if (!is_string($folder)) $folder = (string)$folder; if (!is_array($caps)) $caps = []; $out[$folder] = $normalizeCaps($caps); } return $out; }; $validUser = function (string $u): bool { return ($u !== '' && preg_match(REGEX_USER, $u)); }; // Single-user mode if (isset($payload['user'], $payload['grants']) && is_array($payload['grants'])) { $user = trim((string)$payload['user']); if (!$validUser($user)) { throw new InvalidArgumentException('Invalid user'); } $grants = $sanitizeGrantsMap($payload['grants']); return ACL::applyUserGrantsAtomic($user, $grants); } // Batch mode if (isset($payload['changes']) && is_array($payload['changes'])) { $updated = []; foreach ($payload['changes'] as $chg) { if (!is_array($chg)) continue; $user = trim((string)($chg['user'] ?? '')); $gr = $chg['grants'] ?? null; if (!$validUser($user) || !is_array($gr)) continue; try { $res = ACL::applyUserGrantsAtomic($user, $sanitizeGrantsMap($gr)); $updated[$user] = $res['updated'] ?? []; } catch (\Throwable $e) { $updated[$user] = ['error' => $e->getMessage()]; } } return ['ok' => true, 'updated' => $updated]; } throw new InvalidArgumentException('Invalid payload: expected {user,grants} or {changes:[{user,grants}]}'); } }