Создание тикета без регистрации [Tickets]

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

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

Создаем в админке группу «Создание отзыва» и даем права на наш контекст (web) TicketUserPolicy и Context. Создаем пользователя ticketUser и добавляем его в группу.

Для авторизации есть простой способ. Создаем сниппет loginTicketUser:
<?php
$ctx = $modx->context->get('key');
$username = 'ticketUser';
$password = '********';
$data = array(
    'username' => $username
    ,'password' => $password
    ,'rememberme' => 0
    ,'login_context' => $ctx
);    
$response = $modx->runProcessor('/security/login', $data);
if ($response->isError()) {
    $modx->log(modX::LOG_LEVEL_ERROR, 'login error. Username: '.$username.', Message: '.$response->getMessage());
}
Теперь нам необходимо отредактировать сниппет TicketForm. В 7 строчке сниппет проверяет авторизован ли пользователь на сайте и если нет, то выдает сообщение. Я закомментировал вывод сообщения вместо этого вызываем наш сниппет:
if (!$Tickets->authenticated) {
	//return $modx->lexicon('ticket_err_no_auth');
	$modx->runSnippet('loginTicketUser');
}
Вот собственно и все. По сути переходя на страницу с созданием тикета мы авторизуем пользователя в нужном нам контексте с соответствующими правами. Для того, чтобы после создания тикета нас не перекидывало на страницу редактирования, можем добавить чанк tplFormUpdate где будем выводить сообщение об успешном добавлении тикета.

Решение не самое красивое но работающее. Если в чем-то не прав сильно не ругайте =)

[UPD]
В качестве альтернативного способа для авторизации можно использовать сниппет без процессора, он оказался быстрее и проще для восприятия.
<?php
$ctx = $modx->context->get('key');
$uid = 4; // ID пользователя
    
if ($user = $modx->getObject('modUser', $uid)) {
	$modx->user = $user;
    $modx->user->addSessionContext($ctx);
}
Хулио Надда
08 апреля 2015, 22:45
modx.pro
18
6 323
+4

Комментарии: 17

Виталий Киреев
09 апреля 2015, 05:26
+3
Зачем менять TicketForm, если авторизацию можно проверить в loginTicketUser и вызывать этот сниппет перед формой?
    Хулио Надда
    09 апреля 2015, 08:33
    0
    Согласен об этом не додумался, думаю можно и так
    Сергей Шлоков
    09 апреля 2015, 07:32
    0
    переходя на страницу с созданием тикета мы авторизуем пользователя в админке
    Почему в админке, если указан контекст web?
    $data = array(
        'username' => $username
        ,'password' => $password
        ,'rememberme' => 0
        ,'login_context' => 'web'
    );
    Отсюда вытекает проблема. Данное решение не работает в других контекстах. Например, [ru] и [en].
      Хулио Надда
      09 апреля 2015, 08:39
      0
      Да не совсем правильно сформулировал. Спасибо, поправил.

      Что касается универсальности можно указать тот контекст где тебе нужно, да и если честно задачи сделать универсальным не стояло. Я просто оч много видел коментов на эту тему и раз уж до чего-то додумался решил поделиться.
        Сергей Шлоков
        09 апреля 2015, 08:59
        +2
        Поправил, но не везде. :)
        В 7 строчке сниппет проверяет авторизован ли пользователь в админке
        Не в админке, а в текущем контексте.
        Если уж ты предложил это как готовое решение, то нужно докрутить до универсальности. Например, так, с учетом предложения Виталия вызывать сниппет перед сниппетом TicketForm:
        <?php
        $ctx = $modx->context->get('key');
        if (!$modx->user->isAuthenticated($ctx)) {
        	$username = 'ticketUser';
        	$password = '********';
        	$data = array(
        		'username' => $username
        	,'password' => $password
        	,'rememberme' => 0
        	,'login_context' => $ctx
        	);
        	$response = $modx->runProcessor('/security/login', $data);
        	if ($response->isError()) {
        		$modx->log(modX::LOG_LEVEL_ERROR, 'login error. Username: '.$username.', Message: 	'.$response->getMessage());
        	}
        }
          Хулио Надда
          09 апреля 2015, 12:30
          0
          Да я чуть пожже сделаю апдейт. Сейчас работа работа а нужно еще проверить все. Спасибо за советы ребята
      Sergey Leleko
      09 апреля 2015, 11:12
      +1
      Неплохой костыль ) Спасибо автору!
        yani
        09 апреля 2015, 13:44
        +1
        Да, я в свое время к сожалению больше перелопатила) это намного изящнее
          Хулио Надда
          09 апреля 2015, 14:17
          0
          Отвечаю на вопрос Виталия. Если вызвать сниппет просто перед ticketForm то авторизация с первого раза может не пройти, тут нужен аналог preHook в FormIt. Поэтому приходится вносить изменения в ticketForm. Увы, лучшего не придумал

          Что касается контекста, спасибо Сергею за наводку поправил.
            Виталий Киреев
            09 апреля 2015, 15:23
            0
            При авторизации сделайте и сразу будет
            $modx->sendRedirect($modx->resource->id);
              Хулио Надда
              09 апреля 2015, 15:39
              0
              В таком виде редирект идет на ID ресурса, при наличии ЧПУ 404 ошибка
              $modx->sendRedirect($modx->resource->url);
              Тем не менее авторизация только при втором заходе на страницу — не решает проблемы.
            Василий Наумкин
            09 апреля 2015, 15:46
            +1
            Можно попробовать авторизовать без процессора, это должно быть быстрее и удобнее.
            if ($user = $modx->getObject('modUser', 10)) {
            	$modx->user = $user;
            	$modx->user->addSessionContext('web');
            }
              Хулио Надда
              09 апреля 2015, 18:10
              0
              Поэкспериментирую и отпишусь.
                Хулио Надда
                10 апреля 2015, 02:01
                0
                Тоже самое: первый заход на страницу неавторизованный, второй заход уже авторизованный.
                Способ без процессора можно использовать но править TicketForm так или иначе придется =(

                Добавлю Ваш способ как альтернативный сниппет авторизации, мне больше понравилось =)
                  Valery
                  19 декабря 2015, 18:30
                  0
                  А почему бы просто не добавить проверку, авторизован ли пользователь? И, если нет, переадресовывать на эту же страницу. Это, конечно, ужасный костыль, но он работает.
                  if ($response->isError()) {
                      $modx->log(modX::LOG_LEVEL_ERROR, 'login error. Username: '.$username.', Message: '.$response->getMessage());
                  } else {
                      if (!$modx->user->isAuthenticated('web')) {
                          $id = $modx->resource->id;
                          $url = $modx->makeUrl($id,'','','full');
                          $modx->sendRedirect($url);
                      }
                  }
                    brioni
                    25 февраля 2016, 13:20
                    0
                    От чего может не срабатывать кнопка опубликовать и добавление файлов?
                  Александр
                  28 марта 2019, 15:26
                  0
                  А если к группе пользователей (аноним) добавить контексты для добавления тикетов, так будет работать?
                    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                    17