1.修复角色组不能选择权限的报错
2.修复角色创建子角色报权限不够的问题
This commit is contained in:
@@ -19,6 +19,11 @@ class Group extends Backend
|
||||
{
|
||||
protected string $authMethod = 'allAuthAndOthers';
|
||||
|
||||
/**
|
||||
* 角色组表单分配权限树(仅需登录 + 具备角色组管理相关权限,不依赖菜单规则管理权限)
|
||||
*/
|
||||
protected array $noNeedPermission = ['rules'];
|
||||
|
||||
protected ?object $model = null;
|
||||
|
||||
protected string|array $preExcludeFields = ['create_time', 'update_time'];
|
||||
@@ -90,7 +95,7 @@ class Group extends Backend
|
||||
if ($inheritRes !== null) {
|
||||
return $inheritRes;
|
||||
}
|
||||
$rulesRes = $this->handleRules($data);
|
||||
$rulesRes = $this->handleRules($data, $pidInt);
|
||||
if ($rulesRes instanceof Response) return $rulesRes;
|
||||
|
||||
$result = false;
|
||||
@@ -161,7 +166,7 @@ class Group extends Backend
|
||||
if ($inheritRes !== null) {
|
||||
return $inheritRes;
|
||||
}
|
||||
$rulesRes = $this->handleRules($data);
|
||||
$rulesRes = $this->handleRules($data, $pidInt);
|
||||
if ($rulesRes instanceof Response) return $rulesRes;
|
||||
|
||||
$result = false;
|
||||
@@ -296,9 +301,29 @@ class Group extends Backend
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前登录管理员可分配给下级角色组的菜单权限树(与 Rule::getMenus 一致,走角色组管理权限)
|
||||
*/
|
||||
public function rules(Request $request): Response
|
||||
{
|
||||
$response = $this->initializeBackend($request);
|
||||
if ($response !== null) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (!$this->auth->isSuperAdmin() && !$this->canManageRoleGroups()) {
|
||||
return $this->error(__('You have no permission'), [], 401);
|
||||
}
|
||||
|
||||
return $this->success('', [
|
||||
'list' => $this->getAssignableMenuRules($request),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pidInt 上级角色组 ID;大于 0 表示创建/编辑的是下级组,可与当前管理员拥有相同菜单权限
|
||||
* @return array|Response
|
||||
*/
|
||||
private function handleRules(array &$data)
|
||||
private function handleRules(array &$data, int $pidInt = 0)
|
||||
{
|
||||
if (!empty($data['rules']) && is_array($data['rules'])) {
|
||||
$superAdmin = true;
|
||||
@@ -310,7 +335,6 @@ class Group extends Backend
|
||||
$checkedRules[] = $postRuleId;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($allRuleIds as $ruleId) {
|
||||
if (!in_array($ruleId, $checkedRules)) {
|
||||
$superAdmin = false;
|
||||
@@ -320,9 +344,15 @@ class Group extends Backend
|
||||
if ($superAdmin && $this->auth->isSuperAdmin()) {
|
||||
$data['rules'] = '*';
|
||||
} else {
|
||||
$ownedRuleIds = $this->auth->getRuleIds();
|
||||
$ownedRuleIds = $this->normalizeRuleIds($this->auth->getRuleIds());
|
||||
$checkedRules = $this->normalizeRuleIds($checkedRules);
|
||||
|
||||
if (!array_diff($ownedRuleIds, $checkedRules)) {
|
||||
// 仅限制「非下级」角色组:防止子管理员新建与自己平级的全权限组;下级组(pid>0)允许授予相同菜单权限
|
||||
if (
|
||||
$pidInt <= 0
|
||||
&& $ownedRuleIds !== []
|
||||
&& !array_diff($ownedRuleIds, $checkedRules)
|
||||
) {
|
||||
return $this->error(__('Role group has all your rights, please contact the upper administrator to add or do not need to add!'));
|
||||
}
|
||||
|
||||
@@ -338,6 +368,23 @@ class Group extends Backend
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string> $ids
|
||||
* @return array<int>
|
||||
*/
|
||||
private function normalizeRuleIds(array $ids): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($ids as $id) {
|
||||
if ($id === '*' || $id === '' || $id === null) {
|
||||
continue;
|
||||
}
|
||||
$result[] = (int) $id;
|
||||
}
|
||||
|
||||
return array_values(array_unique($result));
|
||||
}
|
||||
|
||||
private function getGroups(Request $request, array $where = []): array
|
||||
{
|
||||
$pk = $this->model->getPk();
|
||||
@@ -500,4 +547,82 @@ class Group extends Backend
|
||||
return null;
|
||||
}
|
||||
|
||||
private function canManageRoleGroups(): bool
|
||||
{
|
||||
foreach (['auth/group/index', 'auth/group/add', 'auth/group/edit', 'auth/Group/index', 'auth/Group/add', 'auth/Group/edit'] as $routePath) {
|
||||
if ($this->auth->check($routePath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function getAssignableMenuRules(Request $request): array
|
||||
{
|
||||
$ids = $this->auth->getRuleIds();
|
||||
$where = [];
|
||||
if (!in_array('*', $ids, true)) {
|
||||
$where[] = ['id', 'in', $ids ?: [0]];
|
||||
}
|
||||
|
||||
$rules = (new AdminRule())
|
||||
->where($where)
|
||||
->order(['weigh' => 'desc'])
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$toEnglish = !$this->shouldForceMenuTitleZh($request) && $this->shouldTranslateMenuToEnglish();
|
||||
foreach ($rules as $idx => $rule) {
|
||||
$title = $rule['title'] ?? '';
|
||||
if (is_string($title) && $title !== '') {
|
||||
$rules[$idx]['title'] = $toEnglish ? $this->menuTitleToEn($title) : $this->menuTitleToZh($title);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->tree->assembleChild($rules);
|
||||
}
|
||||
|
||||
private function shouldTranslateMenuToEnglish(): bool
|
||||
{
|
||||
$lang = function_exists('locale') ? locale() : '';
|
||||
$normalized = is_string($lang) ? strtolower(str_replace('_', '-', trim($lang))) : '';
|
||||
|
||||
return str_starts_with($normalized, 'en');
|
||||
}
|
||||
|
||||
private function shouldForceMenuTitleZh(Request $request): bool
|
||||
{
|
||||
$flag = $request->get('force_menu_zh') ?? $request->post('force_menu_zh');
|
||||
|
||||
return in_array($flag, [1, '1', true, 'true', 'yes', 'on'], true);
|
||||
}
|
||||
|
||||
private function menuTitleToZh(string $title): string
|
||||
{
|
||||
static $zhMap = null;
|
||||
if (!is_array($zhMap)) {
|
||||
$mapFile = app_path() . '/common/lang/zh-cn/admin_rule_title.php';
|
||||
$loaded = is_file($mapFile) ? include $mapFile : [];
|
||||
$zhMap = is_array($loaded) ? $loaded : [];
|
||||
}
|
||||
|
||||
return isset($zhMap[$title]) && is_string($zhMap[$title]) ? $zhMap[$title] : $title;
|
||||
}
|
||||
|
||||
private function menuTitleToEn(string $title): string
|
||||
{
|
||||
static $enMap = null;
|
||||
if (!is_array($enMap)) {
|
||||
$mapFile = app_path() . '/common/lang/en/admin_rule_title.php';
|
||||
$loaded = is_file($mapFile) ? include $mapFile : [];
|
||||
$enMap = is_array($loaded) ? $loaded : [];
|
||||
}
|
||||
|
||||
return isset($enMap[$title]) && is_string($enMap[$title]) ? $enMap[$title] : $title;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user