165 lines
5.2 KiB
PHP
165 lines
5.2 KiB
PHP
<?php
|
||
|
||
namespace App\Utilities;
|
||
|
||
use App\Models\Auth\User;
|
||
use App\Models\Auth\UserAccessGroup;
|
||
|
||
class SidebarPermissions
|
||
{
|
||
private const LEGACY_PAGE_KEYS = [
|
||
'refunds/small-payment-work-orders' => 'financial-operations/small-payment-work-orders',
|
||
];
|
||
|
||
private const FINAL_SECTION_KEYS = [
|
||
'supplier-payables' => 'supplier-payables-final',
|
||
'courier-payables' => 'courier-payables-final',
|
||
];
|
||
|
||
public static function settings(): array
|
||
{
|
||
$value = setting('system.sidebar_permissions', []);
|
||
|
||
if (is_string($value)) {
|
||
$value = json_decode($value, true) ?: [];
|
||
}
|
||
|
||
return is_array($value) ? $value : [];
|
||
}
|
||
|
||
public static function subjectKey(User $user): string
|
||
{
|
||
$userKey = 'user_' . $user->id;
|
||
$settings = self::settings();
|
||
|
||
if (in_array($userKey, $settings['configured'] ?? [], true)) {
|
||
return $userKey;
|
||
}
|
||
|
||
return 'role_' . SystemAccess::roleName($user);
|
||
}
|
||
|
||
public static function allowedKeys(User $user): ?array
|
||
{
|
||
if (SystemAccess::isSuperAdmin($user)) {
|
||
return null;
|
||
}
|
||
|
||
$settings = self::settings();
|
||
$userSubject = 'user_' . $user->id;
|
||
if (in_array($userSubject, $settings['configured'] ?? [], true)) {
|
||
return self::normalizeAllowedKeys((array) ($settings['subjects'][$userSubject] ?? []));
|
||
}
|
||
|
||
$groups = UserAccessGroup::forUser($user);
|
||
if ($groups->isNotEmpty()) {
|
||
return self::normalizeAllowedKeys(
|
||
$groups->flatMap(fn ($group) => $group->page_permissions ?? [])->all()
|
||
);
|
||
}
|
||
|
||
$subject = 'role_' . SystemAccess::roleName($user);
|
||
|
||
if (! in_array($subject, $settings['configured'] ?? [], true)) {
|
||
return null;
|
||
}
|
||
|
||
return self::normalizeAllowedKeys((array) ($settings['subjects'][$subject] ?? []));
|
||
}
|
||
|
||
public static function navigationFor(User $user): array
|
||
{
|
||
$navigation = BusinessNavigation::all();
|
||
$allowed = self::allowedKeys($user);
|
||
|
||
if ($allowed === null) {
|
||
return $navigation;
|
||
}
|
||
|
||
return array_values(array_filter(array_map(function (array $section) use ($allowed) {
|
||
$sectionKey = $section['slug'];
|
||
|
||
if (in_array($sectionKey, $allowed, true)) {
|
||
return $section;
|
||
}
|
||
|
||
$pages = array_values(array_filter(array_map(function (array $page) use ($allowed, $sectionKey) {
|
||
$pageKey = $sectionKey . '/' . $page['slug'];
|
||
|
||
if (in_array($pageKey, $allowed, true)) {
|
||
// 若有 children,保留 children 的精确权限过滤
|
||
if (! empty($page['children'])) {
|
||
$page['children'] = array_values(array_filter($page['children'], function (array $child) use ($allowed, $sectionKey) {
|
||
return in_array($sectionKey . '/' . $child['slug'], $allowed, true);
|
||
}));
|
||
}
|
||
return $page;
|
||
}
|
||
|
||
// 子页面可能在 allowed 列表中(独立 URL),父级分组也允许展开
|
||
if (! empty($page['children'])) {
|
||
$visibleChildren = array_values(array_filter($page['children'], function (array $child) use ($allowed, $sectionKey) {
|
||
return in_array($sectionKey . '/' . $child['slug'], $allowed, true);
|
||
}));
|
||
if (! empty($visibleChildren)) {
|
||
$page['children'] = $visibleChildren;
|
||
return $page;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}, $section['pages'] ?? [])));
|
||
|
||
if (! empty($pages)) {
|
||
$section['pages'] = $pages;
|
||
|
||
return $section;
|
||
}
|
||
|
||
return null;
|
||
}, $navigation)));
|
||
}
|
||
|
||
public static function allKeys(): array
|
||
{
|
||
$keys = [];
|
||
|
||
foreach (BusinessNavigation::all() as $section) {
|
||
$keys[] = $section['slug'];
|
||
|
||
foreach ($section['pages'] ?? [] as $page) {
|
||
$keys[] = $section['slug'] . '/' . $page['slug'];
|
||
|
||
foreach ($page['children'] ?? [] as $child) {
|
||
$keys[] = $section['slug'] . '/' . $child['slug'];
|
||
}
|
||
}
|
||
}
|
||
|
||
return $keys;
|
||
}
|
||
|
||
public static function normalizeAllowedKeys(array $keys): array
|
||
{
|
||
$normalized = [];
|
||
|
||
foreach ($keys as $key) {
|
||
$key = (string) $key;
|
||
$normalizedKey = self::LEGACY_PAGE_KEYS[$key] ?? $key;
|
||
$normalized[] = $normalizedKey;
|
||
|
||
foreach (self::FINAL_SECTION_KEYS as $sectionKey => $finalSectionKey) {
|
||
if ($normalizedKey === $sectionKey || str_starts_with($normalizedKey, $sectionKey . '/')) {
|
||
$normalized[] = $finalSectionKey;
|
||
}
|
||
}
|
||
|
||
if ($key === 'refunds') {
|
||
$normalized[] = self::LEGACY_PAGE_KEYS['refunds/small-payment-work-orders'];
|
||
}
|
||
}
|
||
|
||
return array_values(array_unique($normalized));
|
||
}
|
||
}
|