Вопросы про права на Тикеты

Василий, привет!
Произошло у меня тут непонимание с назначение прав на тикеты. Сделать так, как мне было надо — я сделал, помощи не требуется :-) Просто хотелось бы разобраться почему это так, а не иначе.

В общем, начну с начала. Сайт — доска объявлений. Юзеры с фронтенда создают объявления, которые по умолчанию не опубликованы. А модераторы уже проходятся по всем новым объявлениям и решают — публиковать их или нет. Модераторы так же могут создавать и редактировать любые объявления. И всё это с фронтенда.
Естесственно, для такой задачи выбрал Tickets :-)

Изначально, нужной группе юзеров надо добавить политику доступа TicketUserPolicy с разрешениями:
ticket_delete, ticket_publish, ticket_save, comment_save, load, list, view
И вот здесь первая непонятка:
В шаблоне политики TicketsUserPolicyTemplate не отображаются load, list, view. Мало того, они так же не отображаются и в самой политике TicketUserPolicy. А в списке всех политик доступа напротив TicketUserPolicy стоит 7 из 5. Т.е. изначально всего разрешений, относящихся непосредственно к тикетам 4 штуки. Это — ticket_delete, ticket_publish, ticket_save, comment_save. Плюс 3 load, list, view. Это логично. Но вот 7 из 5?? Почему их в списке-то не видно?
Ну ладно, допустим на это пофиг, но вот здесь зарыта другая собака — если я изменил хотя бы одно разрешение в политике TicketUserPolicy (или скопировал эту политику, или создал новую на основе шаблона), то в списке политик будет уже истинное нормальное число. Т.е. было 7 из 5, снял одну галочку с одного из разрешений, стало 3 из 5. Значит разрешения load, list, view слетели и теперь группе пользователей надо не только назначать политику TicketUserPolicy, но и отдельно назначать load, list, view. По-моему, такой момент — это как-то не правильно.

Дальше. Когда встала задача разрешить модераторам редактировать любое объявление (т.е. любой тикет), то наткнулся на момент, когда тикет может редактировать только автор этого самого тикета и никто другой. Вот эта проверка:
if ($this->object->createdby != $this->modx->user->id && !$this->modx->hasPermission('edit_document')) {
    return $this->modx->lexicon('ticket_err_wrong_user');
}
Обойти это никак не получилось, пришлось тупо закомментить проверку на автора:
if (/*$this->object->createdby != $this->modx->user->id && */!$this->modx->hasPermission('edit_document')) {
    return $this->modx->lexicon('ticket_err_wrong_user');
}
Может на будущее как-то предусмотреть этот момент и вынести это на уровень политик? В отдельное разрешение, к примеру «edit_not_authored_ticket» (редактировать не свой тикет)?
p.s. возможно я недоглядел и такая возможность уже заложена?

И вот всё сохранялось и всё изменялось как надо. Но в какой-то момент (реально не знаю почему до этого всё работало как надо) возникла новая проблема.
Здесь предыстория — в создаваемых тикетах тайтлы формируются автоматически и алиасы, соответственно, тоже. Из-за того, что была вероятность дублирования алиасов, было принято решение добавлять к алиасу id ресурса, т.е. "{id}-{alias}". Т.к. узнать id нового тикета можно только после его создания, то был сделан плагин, который на создание нового тикета менял алиас на нужный. Это изменение работало через процессор, дабы отлавливать ошибки и соблюдать каноны.
Потом (из-за своих внутренних причин по организации кода) действо по изменению алиаса было перенесено в и без того до неузнаваемости изменённый сниппет TicketForm и на данный момент осуществляется через метод saveTicket (там же тоже через процессоры всё работает).
Т.е. схематично выглядит это всё как-то так:
/* ... */
$data = array(/* this is ticket's data*/);
// generate pagetitle
$generatedPagetitle	= /* ... */;
$data['pagetitle']	= $generatedPagetitle;
// save
$result = $Tickets->saveTicket($data);
if (isset($result['error'])) {
	$modx->log(MODX_LOG_LEVEL_ERROR, $result['error']));
	$output = $Tickets->getTicketForm($result);
}
// not error
else {
	// get resource
	$resource	= $modx->getObject('modResource', $result['id']);
	// set alias
	$id		= $resource->id;
	$alias		= $resource->alias;
	if (strpos($alias, $id.'-') !== 0) {
		$result = $Tickets->saveTicket(array_merge($resource->toArray(), array(
			'tid'	=> $result['id'],
			'alias'	=> $id.'-'.$alias,
			'uri'	=> ''
		)));
	}
	if (isset($result['error'])) {
		$modx->log(MODX_LOG_LEVEL_ERROR, $result['error']));
		$output = $Tickets->getTicketForm($result);
	}
	// not error
	else {
		/* other code */
	}
}
/* ... */

Так вот, всё это вроде как даже работало, пока не произошло очередная странность с политиками, а именно — в момент изменения алиаса в лог начали падать ошибки "ticket_err_wrong_user", т.е. о том, что сохранить тикет может только юзер его создавший.
Что за дела? Подумал я. В процессе копания вспомнил, что в уже рассмотренной мною проверке
if (/*$this->object->createdby != $this->modx->user->id && */!$this->modx->hasPermission('edit_document')) {
    return $this->modx->lexicon('ticket_err_wrong_user');
}
требуются разрешения "edit_document". Решил проверить — добавил группе пользователей разрешение "edit_document" и, о чудо, всё взлетело. Вопрос — почему до этого никогда не требовалось явного указания разрешения "edit_document" в политике пользователей и всё прекрасно работало? Ведь по логике, это разрешение у юзера всегда должно быть указано в явном виде, это ж блин разрешение на редактирование документов! Почему никогда не указывал и работало, а тут вдруг перестало?

Такие вот возникли проблемы и вопросы. В общем, сейчас-то всё работает, но всё-равно хотелось бы разобраться на будущее.

Будут какие-нибудь мысли? :-)
Алексей Карташов
03 июня 2013, 17:39
modx.pro
2 152
0

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

Василий Наумкин
04 июня 2013, 06:31
0
1. Про load, list и view — это я затупил, нельзя так делать. Нужно задавать 2 политики юзерам, на тикеты, и на это. Хотел сделать удобнее — но не вышло.

2. Эта проверка позволяет редактировать тикет автору и любому юзеру, у которого есть право редактировать ресурсы сайта
if ($this->object->createdby != $this->modx->user->id && !$this->modx->hasPermission('edit_document')) {
	return false;
}
else {
	// работаем
}
У тебя же, скорее всего, просто закэшировались права, пока настраивал. Обычное явление, надо выходить с контекста, админки, чистить куки — только тогда можно быть уверенным, что кэша нет.

3. С алиасами, думаю, та же фигня — кэш. Ну или ты еще что-то делал, а сейчас не помнишь.

На будущее — плагины вызываются из процессора, как правило. Запускать еще один процессор, чтобы обработать события из другого процессора — нифига не по канону. Надо сразу в плагине писать своё изменение, тем более, что это всего 2 строчки.
    Алексей Карташов
    04 июня 2013, 11:25
    0
    2. Да, чёрт побери, вот это у меня затуп. До меня только сейчас дошло, что закомментив, я наоборот сломал, а не починил xD
    3. Просто здесь я исходил из логики, что если менять алиас путём обычного
    $resource->set('alias', $newAlias);
    $resource->save();
    и есть ещё какой-нибудь плагин, который работает на сохранение документа, и этот другой плагин отрабатывает ДО моего плагина, то изменение алиаса тот плагин уже не увидит. Ведь сайт-то я сейчас доделаю, отдам заказчику и повлиять на то, как его будут дальше дорабатывать, я уже никак не смогу (вдруг он порядок выполнения плагинов изменит, мало ли, всякое бывает). Поэтому хотел предусмотреть все варианты, чтобы ни где ничего случайно не поломалось.
    Но видать и правда правильней через методы xPDO сохранять.

    Спасибо, в очередной раз, за консультацию! :-)
      Василий Наумкин
      04 июня 2013, 11:26
      0
      Ну так ты меняй
      $modx->event->params['object']->set();
      или как то так. В общем, то что по ссылке передается — тогда и другие плагины должны отработать.
        Алексей Карташов
        04 июня 2013, 11:40
        0
        А, вон оно как. Теперь понял. Просто я всегда объект ресурса либо через xPDO получал, либо просто через переменную $resource. Ведь в плагинах могут быть доступны какие-либо переменные. В On(Before)DocFormSave доступны $id, $resource, $mode.
        Теперь буду знать :-) Спасибо!

        А после изменения значения через set():
        $modx->event->params['object']->set();
        в этом же плагине ->save() делать надо/обязательно? Чтобы другие плагины изменения заметили?
          Алексей Карташов
          04 июня 2013, 11:59
          0
          в этом же плагине ->save() делать надо/обязательно?
          по ходу тупой вопрос))
    Yani
    21 ноября 2013, 00:53
    0
    Василий, доброй ночи.
    Возник вопрос. Создаю менеджера сайта, добавляю контейнер тикетов в ресурс, назначаю в контекте mgr права TicketSectionPolicy и так же доступ к контексту web тикетВипПолиси. Сама политика доступа ограничена 160 пунктами из 172. казалось бы все разрешено. а при создании менеджером тикета пишет доступ закрыт =(
      Yani
      21 ноября 2013, 01:01
      0
      повключала то, что было отключено.
      в итоге, дело в политике dashboards.
      хм, а я обычно ее отключаю.
      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
      7