D9: А это нормально, что для uid = 1 не отображаются чекбоксы ролей?

Аватар пользователя OldWarrior OldWarrior 25 сентября в 23:39

Случайно споткнулся о не совсем понятную вещь.

Писал некий механизм, проверяющий, что среди ролей пользователя имеются 'manager' или 'administrator'. Пользователь, к слову, не именно текущий, а скажем так, инициировавший некоторое событие в системе (по сути что-то вроде журнала/истории изменения данных сотрудниками сайта). Ну, примерно так:

<?php
...
$user = \Drupal\user\Entity\User::load($orig_uid);
if (
$user->hasRole('manager') || $user->hasRole('administrator')) {
  
$uid $orig_uid;
}
...
?>

Захожу под uid = 1 (т.е. самый толстый админ). Тестирую этот механизм и обнаруживаю, что именно для меня он не работает. Иду смотреть что не так в профиль uid 1. И вижу, что у супер-пупер-админа стоит только лишь одна галка напротив роли "Аутентифицированный пользователь".

Включаю роль "администратор", сохраняю. "Изменения сохранены". Ок, открываю профиль, кручу вниз и вижу, что чекбокс роли "Администратор" по-прежнему отключен.

Лёгкий разрыв шаблона, как говорится. Опять включаю эту галку и, за компанию, дополнительно включаю роль "менеджер", сохраняю. "Изменения сохранены". Опять открываю профиль, кручу вниз - в поле все эти установленные чекбоксы по-прежнему отключены (кроме, разумеется, "Аутентифицированный пользователь").

Возникает смутное предположение: я, возможно, отстал от жизни и теперь всё как-то должно происходить иначе? На всякий случай выбираю другого пользователя и ставлю ему чекбоксы админа и менеджера. С замиранием сердца сохраняю профиль и - внезапно - галки установились!

Но это же не мой профиль, а что делать с моим?

Тут я наконец обнаруживаю, что в списке пользователей третья колонка отображает список ролей конкретного пользователя. И - внезапно! - у uid = 1 теперь стоит две роли: "Менеджер" и "Администратор".

Не веря своим глазам, возвращаюсь в профиль и вижу ту же унылую картину: чекбоксы этих ролей выключены.

Ну и ладно, ну их к лешему, эти чекбоксы. Возвращаюсь к своему коду и проверяю работу. Да, всё ОК, роль "Администратор" присутствуют, код отрабатывает так, как намечалось.

Возникают два вопроса:

1. Это какое-то штатное поведение формы профиля для uid = 1? Форму профиля не альтерили, нет никакой сторонней "химии".

2. Какое решение для вышеприведённого кода тогда более уместно в случае, если нет возможности поставить необходимые роли для uid = 1 ? Проверять тогда не $user->hasRole('administrator'), а $user->id() == 1 ? Например (применительно к вышеприведённому коду):

<?php
...
$user = \Drupal\user\Entity\User::load($orig_uid);
if (
$user->hasRole('manager') || $user->hasRole('administrator') || $user->id() == 1) {
  
$uid $orig_uid;
}
...
?>

Комментарии

Аватар пользователя OldWarrior OldWarrior 26 сентября в 2:05

PS. Продолжение истории.

Через час после написания топика обнаружил, что проверка роли а-ля $user->hasRole('administrator') по-прежнему не работает. Я был введён в заблуждение другим условием (оно шло выше и в код примера не попало).

В общем, установка роли 'administrator' для UID = 1 не сказывается на программной проверке. Метод hasRole() похоже вообще не обнаруживает никакие роли для UID = 1 (для любого другого пользователя с ролью менеджера всё работает). Я не пойму, в чём тут дело. Пока решил вопрос так, как писал выше (т.е. добавил $user->id() == 1) :

<?php
...
$user = \Drupal\user\Entity\User::load($orig_uid);
if (
$user->hasRole('manager') || $user->hasRole('administrator') || $user->id() == 1) {
  
$uid $orig_uid;
}
...
?>

Но как-то мне это не нравится.

Аватар пользователя ivnish ivnish 26 сентября в 11:14

OldWarrior wrote: Это какое-то штатное поведение формы профиля для uid = 1

Да. Юзер с id = 1 всегда имеет все права на всё и это не изменить. Странно, что ты этого не знал

OldWarrior wrote: Какое решение для вышеприведённого кода тогда более уместно в случае, если нет возможности поставить необходимые роли для uid = 1

Не использовать юзера с id = 1 в работе.

Аватар пользователя OldWarrior OldWarrior 26 сентября в 13:34

ivnish wrote: Да. Юзер с id = 1 всегда имеет все права на всё и это не изменить. Странно, что ты этого не знал

Спасибо за подтверждение. Мне и самому странно. Но:

1. В своё оправдание могу заметить, что в каких-то предыдущих версиях D (и, по-моему, ещё даже в 8.x) чекбоксы у uid = 1 по всем ролям всё же стояли. Понятно, что у него и так все права по умолчанию.

2. Опять же сбивает с толку то, что установка чекбоксов перед сохранениям профиля всё же сказывается на отображении ролей в списке пользователей (картинка №2 выше). То есть они вроде бы обрабатываются при сохранении, но при повторной загрузке формы ставятся в FALSE (причём за исключением 'authenticated').

3. Сам факт того, что все чекбоксы кроме 'authenticated' доступны для включения (т.е. не 'disabled') опять же создаёт какую-то неоднозначность относительно их использования.

4. Наконец, я помню, что метод hasRole() (или, возможно, User::getRoles() - точно уже не помню) на D8 таки возвращал роль/роли для uid = 1. То есть, для меня это сейчас реально какой-то сюрприз.

ivnish wrote: Не использовать юзера с id = 1 в работе.

Ну вот это, к сожалению, исключено.

Аватар пользователя ivnish ivnish 26 сентября в 13:40

OldWarrior wrote: чекбоксы у uid = 1 по всем ролям всё же стояли

Это абсолютно ни на что не влияет.

OldWarrior wrote: Сам факт того, что все чекбоксы кроме 'authenticated' доступны для включения (т.е. не 'disabled') опять же создаёт какую-то неоднозначность относительно их использования

Для новичков да. Странно, что у тебя такие же чувства.

OldWarrior wrote: Ну вот это, к сожалению, исключено.

Кто заставляет тебя использовать этого юзера и почему?

Аватар пользователя OldWarrior OldWarrior 26 сентября в 14:02

ivnish wrote: Это абсолютно ни на что не влияет.

Да понимаю, что не влияет. ) Но тем не менее hasRole(), как я писал выше, у меня таки работал ранее. Собственно, задача была добиться именно обнаружения соответствующих ролей у UID = 1.

ivnish wrote: Для новичков да. Странно, что у тебя такие же чувства.

Ну да, значит, я новичок, раз уж испытываю какие-то странные чувства. Вы как бы второй раз уже намекаете на это. Что ж мне теперь делать-то?

ivnish wrote: Кто заставляет тебя использовать этого юзера и почему?

Формально - никто. Но есть ряд соображений, по которым создание отдельного профиля/аккаунта для "главного" админа вызовет лишние вопросы и в будущем - может запутать ситуацию с аккаунтами в целом. Это не мой проект, я тут исполнитель.

Аватар пользователя ivnish ivnish 26 сентября в 14:19

OldWarrior wrote: Вы как бы второй раз уже намекаете на это.

Я не намекаю. Я недоумеваю Smile

OldWarrior wrote: для "главного" админа вызовет лишние вопросы

Смысл главного админа в том, что он всё может и у него всё отображается. Если ты хочешь ограничивать в чем-то главного админа, то лучше создать для этого отдельную роль и отдельного юзера

Аватар пользователя gun_dose gun_dose 26 сентября в 17:30

Очень похоже на какой-то глюк. В коде методов hasRole и getRoles нет никаких особых кейсов для uid=1. И вообще, права первого юзера неограничены при проверке пермишенов. А вот проверка ролей должна работать, как у всех. Я постоянно с этим сталкиваюсь, если во вьюхе поставить ограничение доступа по роли, которой нет у админа, то админу пишет "доступ запрещён". Если же ограничить доступ не по роли, а по пермишену, то всё показывает.

Аватар пользователя adano adano 26 сентября в 18:06

OldWarrior wrote: Тут я наконец обнаруживаю, что в списке пользователей третья колонка отображает список ролей конкретного пользователя. И - внезапно! - у uid = 1 теперь стоит две роли: "Менеджер" и "Администратор".
Не веря своим глазам, возвращаюсь в профиль и вижу ту же унылую картину: чекбоксы этих ролей выключены.

На стандартном профиле, "из коробки" всё норм. Описанное поведение выше отсутствует.

Аватар пользователя OldWarrior OldWarrior 26 сентября в 20:35

ivnish wrote: Я не намекаю. Я недоумеваю

Ну что, бывает и так. Давно не занимался вопросами ролей, в частности - особенностями получения ролей для uid = 1.

Разумеется, я прогуглил вопрос прежде, чем открывать топик. И в том-то и дело, что никаких явных подтверждений вышеописанного поведения не нашёл. Как и в целом - описания состояния чекбоксов ролей для uid = 1. То есть, эмпирически/субъективно мы тут все знаем, что "толстый админ" в Друпале имеет по умолчанию все права, причём установленные перманентным образом поскольку uid = 1. Но это никак не помогает пониманию странной ситуации с чекбоксами и тем более странной - с методами ::hasRole() и ::getRoles().

Кроме того, это создаёт ещё одну проблему: как донести эти эмпирически полученные сведения об особенностях Друпала до заказчика? До человека, который привык понимать, что если чекбокс установлен - значит "оно включено". И если тут какое-то другое поведение, которое нужно трактовать со ссылкой типа "ну вот Друпал - он такой, у него так", то, боюсь, что это опять же зацепит вопросы кармы и репутации Друпала. Как-то так.

Ну и, как писал выше, есть ряд соображений (которые долго излагать), по которым лучше обрабатывать uid = 1 так же, как и остальных администраторов, то есть - по роли.

В общем, спасибо за ответы.

gun_dose wrote: А вот проверка ролей должна работать, как у всех.

adano wrote: На стандартном профиле, "из коробки" всё норм. Описанное поведение выше отсутствует.

Спасибо. Я что-то теряюсь и не знаю, что тут может быть причиной. Есть какие-либо соображения?

Из контрибных модулей на проекте установлено немного, и (вроде бы) ни один из них не должен влиять на сущности пользователя, роли и разрешения:

  • admin_toolbar
  • backup_migrate
  • devel
  • entity_reference_revisions
  • field_group
  • form_options_attributes
  • paragraphs

Остальное - кастомные модули, но все писал я и ни в одном нет никаких хуков/надстроек, каким-либо образом изменяющих стандартную форму и механизм сохранения профилей пользователей.

Аватар пользователя adano adano 26 сентября в 21:21

OldWarrior wrote: Есть какие-либо соображения?

имхо, на стандартный профиль не просто так намекнул... Думаю, где-то там твой баг.

Скорее всего, тут где-то ответ или в связанных issues:
https://www.drupal.org/project/drupal/issues/540008

Аватар пользователя OldWarrior OldWarrior 26 сентября в 21:28

adano wrote: профиль не просто так намекнул... Думаю, где-то там твой баг.

Да тоже стандартный профиль. К сожалению, уже не могу сказать, наблюдалась ли эта проблема сразу после установки. Обнаружил только прошлой ночью.

adano wrote: Скорее всего, тут где-то ответ или в связанных issues:
https://www.drupal.org/project/drupal/issues/540008

Да, я ночью уже просматривал это. Не обнаружил ничего, явно объясняющего вышеописанное. Возможно, стоит внимательнее перечитать.

Аватар пользователя OldWarrior OldWarrior 8 октября в 13:06

Продолжение истории.

К сожалению, решение вышеописанной проблемы с чекбоксами и категорическим отказом обнаруживать роли у uid = 1 так и не нашёл.

Но добавилась ещё одна странность. Потребовалось ввести в поля стандартного профиля пользователя одно кастомное поле с JSON-данными типа простого неформатированного long-text и записывать в него некоторое множество специфических настроек, уникальных для текущего пользователя. Ну, просто обычный длинный текст, иными словами.

И в дополнение к вышеописанному поведению с чекбоксами профиль uid = 1 тут тоже наотрез отказался сохранять что-либо в кастомное поле. Неважно как именно сохраняются данные: программно ли или через UI-поля профиля (как обычная произвольная/тестовая строка) - результат отрицательный. Сущность сохраняется, но поле не инициализировано и даже вообще отсутствует в entity values (как отрапортовал dpm). Примечательно, что для любого другого пользователя с любой ролью сохранение полей профиля работает как обычно.

Поотключал некоторые модули, потенциально (на мой взгляд) способные вмешиваться в сохранение сущности пользователя (например, devel и пр.). Безрезультатно. Разбираться в проблеме уже, к сожалению, не было времени. Было в итоге согласовано и принято решение не использовать аккаунт uid = 1 в дальнейшей повседневной деятельности. Как предлагал выше ivnish. Хоть это и может создать некоторые неудобства в будущем.

В общем, капитуляция.

По прежнему, приветствуются любые соображения по этому поводу.

Аватар пользователя adano adano 9 октября в 9:38

Может, банально, баг в админской теме? Кастомные js-скрипты/библиотеки?

Аватар пользователя OldWarrior OldWarrior 10 октября в 0:13

Да вроде бы не похоже.

Тема админки стандартная, seven для D9. Кастомные скрипты для админки - да, подключаются, но только на специфических роутах/формах, для профиля пользователя ничего такого нет. Да и для другого любого пользователя всё работает. Например, могу зайти под другим админом (не uid = 1) и что угодно вбить/сохранить в полях своего профиля. Включая пресловутые чекбоксы - они тоже работают.