Symfony 4: Как подключить пользователя в контроллере по запросу AJAX? - PullRequest
0 голосов
/ 04 июня 2018

В последнее время я работаю над системой уведомлений.Я дал возможность создавать их и пользователю, который их получает, читать их, и теперь я хочу, чтобы пользователь мог их отклонить и удалить.Я хочу обрабатывать удаление там асинхронно, чтобы пользователю не приходилось обновлять страницу каждый раз, когда он отклоняет уведомление.

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

Но некоторые более важные сообщения остаются, пока пользователь не щелкнет по ним.Поэтому в javascript, когда пользователь щелкает их, я отправляю Ajax-запрос контроллеру, который должен удалить уведомление.Проблема в том, что контроллер не может получить доступ к подключенному пользователю!Я пытался использовать $this->getUser() и $tokenInterace->getToken(), но оба возвращают null.

. Доступ к пользователю позволил бы мне проверить, действительно ли он владеет уведомлением, а не просто набрать случайный URL, пытаясьподавить чье-то уведомление.Это также позволило бы очистить все уведомления пользователя (как еще одна функция).

Здесь приведены все настройки и код, которые, я думаю, могут относиться к этой проблеме.

Symfony

# config/packages/framework.yaml
framework:
    session:
        handler_id: ~

SecurityBundle

# config/packages/security.yaml
security:
    # ...
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt))/
            security: false

        login:
            pattern: ^/login$
            anonymous: true

        main:
            pattern: ^/
            anonymous: false
            form_login:
                # ...
            remember_me:
                secret: '%env(APP_SECRET)%'
                lifetime: 604800

    access_control:
        # - { path: ^/api, role: ROLE_USER }
        # If I uncomment this line, Ajax request get redirected to login page 
        # ...

FOSUserBundle

# config/packages/fos_user.yaml
fos_user:
    db_driver: orm
    firewall_name: main
    user_class: App\Entity\User\User
    from_email:
        address:        '%env(MAILER_URL)%'
        sender_name:    '%env(MAILER_URL)%'

Контроллер

// The controller is imported with options prefix="/api", name_prefix="api_" and expose=true
// (name_prefix is new from Symfony 4.1, it permits to automatically prefix all imported route names)

/**
 * @Route("/notification", name="notification_")
 */
 class NotificationApiController extends BaseController
 {
     /**
      * @Route("/{id}", name="delete", requirements={"id"="\d+"})
      * @Method({"DELETE"})
      */
     public function delete(Notification $notification, TranslatorInterface $translator)
     {
         if ($notification->getUser() !== $this->getUser()) {
             return $this->createJsonResponse([
                 'error' => $translator->trans('error.notification.not_owner'),
             ], 403);
         }

         $em = $this->getDoctrine()->getEntityManager();
         $em->remove($notification);
         $em->flush();

         return $this->createJsonResponse();
     }

     /**
      * @Route("/clear", name="clear")
      * @Method({"DELETE"})
      */
     public function clear(NotificationRepository $notificationRepository, TranslatorInterface $translator)
     {
         $user = $this->getUser();

         if ($user === null) {
             return $this->createJsonResponse([
                 'error' => $translator->trans('error.notification.not_user'),
             ]);
         }

         $notificationRepository->clearForUser($user);

         return $this->createJsonResponse();
     }
 }

Javascript

// Notifications are in the header
const $header = document.querySelector('header');
$header.addEventListener('click', (e) => {
  const $notif = e.target.closest('.notif');
  if ($notif !== null) {
    // Parse the notification id
    const id = +$notif.getAttribute('data-id');
    if (id !== null) {
      const route = Routing.generate('api_notification_delete', { id });

      // I don't care about browser support
      fetch(route, { method: 'DELETE' })
        .then((response) => {
          // check for errors
          return response.json();
        })
        .then((response) => {
          // remove notification from DOM;
        })
    }
  }
});

Я почти уверен, что проблема не в истечении сеанса.Или, может быть, сессия работает иначе для асинхронного запроса?(Это было бы очень странно)

Кто-нибудь когда-либо сталкивался с проблемой, или есть идея, как ее исправить?Если вам нужно что-то еще, не стесняйтесь спрашивать!

РЕДАКТИРОВАТЬ

Я нашел причину проблемы.Это «выборка».Fetch API по умолчанию не использует куки.Чтобы использовать куки, вы должны передавать { credentials: 'same-origin' } в качестве параметра для выборки каждый раз, когда вы используете его (как я обнаружил здесь ).

Надеюсь, это может кому-то помочь однажды!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...