Алексей Карташов

Алексей Карташов

Был в сети 23 ноября 2019, 13:47
Заказы не принимаю
Да, встречал несколько постов, где говорили, что админка пускает без пароля. У меня, этот способ не заработал, конечно (см. выше — проблема была в другом), но ведь чёрт возьми! Как так? Система пускает в админ.панель тупо по логину? Без пароля? И это реально так бывало? Достаточно знать логин админа? Это ведь какая-то особенная жесть, если такое дело вдруг на рабочем сайте обнаружится
Корень проблемы нашёл — как обычно, ссзб.
В форме добавления нового тикета, кроме, собственно, полей тикета, так же есть поля для редактирования данных пользователя. И если пользователь залогинен, то данные автоматом подставляются в эти поля. Если не залогинен, то их надо вписать и юзер автоматом создастся и залогинится. Так вот при добавлении тикета поля пользователя обрабатываются отдельно — если надо — юзер создаётся, если что-то изменилось — юзер обновляется.
Так вот обновление юзера происходило вот так:
function userUpdate ($user, $data) {
	$result			= array();
	$userProfile	= $user->getOne('Profile');
	$userProfile	= $userProfile->toArray();
	// $changedData	= array_diff($data, array_intersect_key($userProfile, $data));
	$changedData	= array_intersect_key($data, $userProfile);
	if (count($changedData)) {
		/**
		 * Всё внимание на массивы, которые передаются в процессор:
		 */
		$response = $this->modx->runProcessor('web/user/update', array_merge(
			$userProfile,
			$user->toArray(),
			$changedData
		));
		if ($response->isError()) {
			$errors = $this->getResponseErrors($response);
			$result = array_merge($result, $errors);
		}
		$this->modx->error->reset();
	}
	return $result;
}

И фишка вышла такая — благодаря $user->toArray() в процессор передаётся так же поле текущего пароля. А точнее не сам пароль, а его хэш (в базе же пароли хешированные лежат). А процессор, получив заполненное поле пароля, делал из него новый хэш и его записывал. Соответственно, пароль-то фактически каждый раз менялся. Вот такой вот я балда :-)

Изначально я считал, что в процессор
достаточно передать id-шник юзера и поля, которые надо изменить. А оказалось, что нифига — этому процессору обязательно нужны ещё логин и мыло (которое надо тянуть из профайла). Поэтому решил перебдеть, собрав все данные в кучу. И зря, как выяснилось)
Переделал на это и всё заработало:
function userUpdate ($user, $data) {
	$result			= array();
	$userProfile	= $user->getOne('Profile');
	$userProfile	= $userProfile->toArray();
	// $changedData	= array_diff($data, array_intersect_key($userProfile, $data));
	$changedData	= array_intersect_key($data, $userProfile);
	if (count($changedData)) {
		$response = $this->modx->runProcessor('web/user/update', array_merge(array(
			'id'		=> $user->id,
			'username'	=> $user->username,
			'email'		=> $userProfile['email']
		), $changedData));

		if ($response->isError()) {
			$errors = $this->getResponseErrors($response);
			$result = array_merge($result, $errors);
		}
		$this->modx->error->reset();
	}
	return $result;
}

Василий, я не зря отвечаю в этой ветке именно тебе, потому что в процессе копания выяснилась интересная особенность тикетов, возможно даже баг.
Помнишь, ты мне как-то помогал разобраться с изменением алиасов при создании тикетов? К алиасу добаляется id тикета в плагине на «OnDocFormSave» вот так:
$resource	= &$modx->event->params['resource'];
$alias		= $resource->get('alias');
$alias		= (strpos($alias, $id.'-') !== 0) ? $id.'-'.$alias : $alias;
$resource->set('alias', $alias);
$resource->save();

У меня в сниппете myTicketForm в самом конце, после всех шаманств и отработки всех процессоров, идёт редирект на этот тикет:
$redirectTo = $modx->makeUrl($result['id'],'','','full');
$modx->sendRedirect($redirectTo);

И вот в чём дело — редирект происходит на uri со старым алиасом, т.е. на тот, который был до моих изменений! Хотя все плагины отработали и всё должно было измениться. Но и это не самое интересное — у самого тикета алиас сохранился таким, каким я его и сделал, с id-шником! Т.е. makeUrl берёт uri документа из какого-нибудь alias_map, а там данные ещё старые. В итоге редирект происходит на не существующий адрес. Но и это ещё не всё — страница открывается! xD
Т.е., положим у тикета сформировался такой алиас — 'this-is-ticket-alias'. В плагине к нему подставляется id тикета: '123-this-is-ticket-alias'. И этот алиас фактически у ресурса и записан, но в кэше лежит 'this-is-ticket-alias', и при редиректе на этот адрес открывается только что созданный тикет (хотя адрес-то фактически не существующий)!
И вот только после того, как в админке что-нибудь изменю/сохраню или просто тыкну «обновить сайт» — кэш очищается и по адресу 'this-is-ticket-alias' как и положено вылезает 404, а сам документ становится доступен по '123-this-is-ticket-alias'.
Такие дела.

В процессе копания пришёл к вот этому.
Заменил код метода на:
$this->xpdo->cacheManager->refresh(array(
	'db' => array(),
	'auto_publish' => array('contexts' => array($this->context_key)),
	'context_settings' => array('contexts' => array($this->context_key)),
	'resource' => array('contexts' => array($this->context_key)),
));
Не помогло.
Потом заменил на одну строчку:
$this->xpdo->reloadContext($this->context_key);
И всё встало на свои места, всё заработало как надо. Только вот теперь чистится весь кэш сайта, а собственная система кэширования тикетов получается не при делах :-(

Выходит проблема именно в кэшировании тикетов. Точнее в очистке кэша.
Как-то так.
Да вот в том-то и дело, что предпосылок к такой проблеме нету совершенно. Обычный Login, обычное добавление ресурсов с фронтэнда с помощью Tickets. Хостинги разные были — проблема везде одна. Логическим/эмпирическим путём пытался сообразить откуда ноги растут — х его знает. Первый раз такое
А если попробовать зайти прям из другого брайзура?
Так же ошибка
Ошибки в логах на сервере есть?
Пусто :-(
Php-apc или другой кэшер включен?
Вроде нет. Во всяком случае с кэшем не игрался и все настройки кэша по умолчанию из коробки.

Сейчас вообще жесть какая-то — после последней попытки логина через Login тупо перестала отображаться форма входа. Вот вообще нету. Папку с кэшем чистил несколько раз (мало ли). Раньше такого не было.
Рискну ответить…
На странице топика у Вас на сайте есть редактирование созданного уже Тикета/Заметки
как это можно реализовать?
Предположим форма добавления тикета находится на странице /post.html с id = 9. Тогда вам в шаблоне тикета надо поставить ссылку вида:
<a href="[[~9]]?tid=[[*id]]">Редактировать</a>
При написании Тикета/Заметки у Вас на сайте отсутствует
как это можно реализовать?
Я правильно понимаю, что вам надо реализовать отсутствие этой галочки? Тогда просто удалите соответствующий html-код из шаблона добавления/редактирования тикета и добавьте внутрь формы вот это:
<input type="hidden" name="published" value="1" />
И еще расскажите пожалуйста, что делают эти три вида режима работы сниппета у TicketForm
getTicketForm — показывает форму добавления/редактирования тикета,
saveTicket — сохраняет тикет,
previewTicket — предпросмотр тикета.
Ваш К.О.

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