В рамках процесса входа в систему / авторизации моего приложения Symfony 4 у меня есть определитель событий, определенный для определения набора групп, к которым у текущего пользователя есть доступ.Это выполняется при каждом запросе:
class DatabaseUserAuthenticationListener {
... //constructor and private vars
public function onKernelController(FilterControllerEvent $event) {
if ($this->authToken && $this->authToken->getUser() !== "anon.") {
$databaseUser = $this->authToken->getUser();
$user = $databaseUser->getUser();
$groups = $this->groupDAO->getUserTree($user);
$privileges = $this->privilegeDAO->getUserPrivileges($user);
$groups->addPrivileges($privileges);
$this->authToken->setAttribute("groupTree", null);
$this->authToken->setAttribute("groupTree", $groups);
}
}
}
Он зарегистрирован здесь как сервис:
App\Utility\Security\DatabaseUserAuthenticationListener:
tags:
- { name: kernel.event_listener , event: kernel.controller }
По сути, это загрузка набора групп, к которым у пользователя есть доступ,и затем заполнение этих групп привилегиями, которые пользователь может сделать для каждой группы.
Это создает объект GroupTree
, который выглядит примерно так:
GroupTree {#444 ▼
#nodeList: array:9 [▶]
#rootNodes: array:2 [▶]
-parents: array:9 [▶]
}
nodeList
показывает всесписок узлов в плоском массиве.rootNodes
имеет все узлы в формате дерева.Если я dump($groups)
прямо перед тем, как позвонить setAttribute
, я получу нечто подобное в nodeList
:
#nodeList: array:9 [▼
14 => GroupNode {#445 ▼
-privileges: array:1 [▼
"VIEW_GROUP" => Privilege {#454 ▶}
]
#nodeId: 14
#nodeObject: Group {#435 ▶}
#children: array:2 [▶]
#parent: null
}
15 => GroupNode {#446 ▶}
...
25 => GroupNode {#453 ▶}
]
Это плоский массив GroupNode
объектов.Каждый GroupNode
объект имеет массив Privilege
объектов, который представляет то, что текущий пользователь может делать с Группой.
Я также должен заявить, что дерево построено путем вызова addNode(GroupNode $node)
, поэтому это невозможнодобавить что-то кроме GroupNode к этому дереву.
Вот Weiedness
У меня есть ParamConverter
, который должен принять идентификатор, переданный контроллером, и посмотретьподнимите id в контексте текущего пользователя (то есть GroupTree
, который я только что поместил в AuthToken) и верните , что GroupNode
(в комплекте с привилегиями пользователя), если оно есть в дереве.
class GroupConverter implements ParamConverterInterface {
private $groupTree;
public function __construct(TokenStorageInterface $tokenStorage) {
if ($tokenStorage->getToken() instanceof UsernamePasswordToken) {
$token = $tokenStorage->getToken();
//I'm setting the groupTree from the UserToken
$this->groupTree = $token->hasAttribute("groupTree") ? $token->getAttribute("groupTree") : null;
}
}
public function apply(Request $request, ParamConverter $configuration) {
$name = $configuration->getName();
if ($this->groupTree && $this->groupTree->keyExists($request->get("id"))) {
//I'm looking at the id passed in by the controller and using it to look up the GroupNode object in from the tree.
$object = $this->groupTree->getItem($request->get("id"));
} else {
throw new NotFoundHttpException("Group not found!");
}
$request->attributes->set($name, $object);
return true;
}
public function supports(ParamConverter $configuration) {
if ($configuration->getClass() === "App\\Model\\Objects\\GroupNode") {
return true;
}
return false;
}
}
Вот странная часть: Единственный раз, когда я возвращаю объект GroupNode
, это когда я прохожу в одном из корневых узлов.Во всех других случаях я получаю что-то, кажущееся случайным ... иногда bool, иногда string, иногда array.Очень странно.
Если бы я был dump($this->groupTree)
сразу после того, как я установил его в конструкторе выше, вот что я получаю в nodeList
(groupTree
то же самое):
#nodeList: array:9 [▼
14 => GroupNode {#249 ▶}
15 => "18"
18 => 1
19 => GroupNode {#243 ▶}
20 => "21"
21 => array:2 [▶]
22 => 0
24 => []
25 => 0
]
14 и 19 (по совпадению?) Оказались корнями.
Итак, чтобы подвести итог проблемы:
GroupTree
объекты не могут есть что-то кроме GroupNode
объектов в nodeList
... и все же это есть. - каждый раз Я проверяю объект
GroupTree
прямо перед тем, как добавить его в качестве атрибута кМой токен пользователя в моем Слушателе, это правильно.Кроме того, это only место, где установлен этот атрибут.Тем не менее, каждый раз, когда я проверяю этот атрибут на токене аутентификации, из моего класса GroupConverter
(который, предположительно) после вызова слушателя, он искажается.
Так что мои вопросы широкие игенерал:
WTH может быть причиной этого?Я делаю что-то явно не так?Правильно ли я понимаю порядок, в котором эти вещи происходят (и действительно ли это имеет значение)?
Спасибо.