Разграничение прав агентов по группам

Moderator: DenisBY

Locked
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Разграничение прав агентов по группам

Post by ULiX »

OTRS v 2.4.7
Используется на крупном металлургическом предприятии.
Используется очень активно, что привело к увеличению числа очередей.
Создана одна очередь для поступающих заявок.
Для ограничения прав создания заявителями заявок в очередях было создано правило (ACL) которое позволяет из интерфейса пользователя (Action => [ 'CustomerTicketMessage' ]) создавать заявки только в одной очереди.
Создание данного правила было вынужденным. Нам не нужно чтобы пользователь сам выбирал категорию своей проблемы - за него это сделают диспетчеры.

Для всех заявителей мы определили одну группу по умолчанию:
$Self->{CustomerGroupAlwaysGroups} = ['customers'];
Без дополнительного правила (ACL) заявитель находящийся в группе customers может создать заявку в любой очереди и видит свои заявки находящиеся в очередях, которым назначена группа 'customers'.
Всем очередям нашей OTRS на данный момент назначена как раз группа 'customers', чтобы пользователь всегда видел свои заявки в интерфейсе заявителя и мог прослеживать их статус.
Если переместить заявку в очередь, группа для которой назначена иная чем 'customers', например 'users', то заявитель теряет свою заявку, и перестает получать какие-либо уведомления на электронный адрес, не смотря на то, что является владельцем-заявителем. Именно поэтому на уровне прав мы не могли решить проблему, назначить группу 'customers' только для одной очереди.

Но с ростом числа очередей появилась необходимость разграничить права различных групп агентов.
* Существуют наборы очередей,
* А также группы агентов которые обслуживают эти очереди.
* Есть группа диспетчеров, которые проверяют общую входящую очередь и распределяют заявки между другими отделами, перемещая заявки.

На данный момент все агенты и диспетчеры имеют полные права на все очереди.
Вроде бы как механизм распределения прав позволяет сделать так, чтоб определенный агент мог только читать заявку и ничего с ней не делать, но как только я забираю у агента права "rw" оставляя при этом все остальные "ro move_into create note owner priority" этот агент тут же теряет возможность видеть заявки. Непонятное поведение!!! При этом если такой пользователь попытается прочитать заявку по прямой ссылке (otrsserver.dom/index.pl?Action=AgentTicketZoom&TicketID=47393) на заявку то видно как действуют эти самые оставленные права "ro move_into create note owner priority". Если к примеру оставить права только "ro" то агент не сможет сделать с заявкой ничего кроме просмотра, печати, и просмотра истории. Если лишить агента вообще каких либо прав, то при просмотре заявки по прямой ссылке, получим отказ в доступе.
Но всё это может перевернуться, если для данной заявки назначить владельцем этого самого агента. В этом случае, даже когда у пользователя нет прав в очереди, в которой находится заявка, он будет иметь полные права над самой заявкой, и это независимо заблокирована заявка на этом агенте или не заблокирована.

Идеальным распределением прав в моем случае было бы
* Назначить каждому набору очередей свою группу.
* Создать роли для каждого набора агентов.
* Назначить для каждой роли права в группах (например дополнительно разрешить перемещение заявок из отдела в отдел начальниками отделов)
* Связать агентов с конкретными ролями.

Но это всё лирика...
ВНИМАНИЕ ВОПРОС!!!
Как агент, имеющий любые права, кроме "rw", будет искать заявки в доступных ему для чтения очередях, если он не видит ни очередей и, как следствие, ни заявок в этих очередях???

ВНИМАНИЕ ВОПРОС НОМЕР 2!!!
Почему когда пользователю выданы права только на перемещение move_into в конкретную группу, то очередь ассоциированная с этой группой отображается в списке возможных перемещений только при подробном рассмотрении заявки (Action=AgentTicketZoom), но не позволяется переместить ту же заявку из интерфейса просмотра очередей (Action=AgentTicketQueue&View=Preview)??? Если же выдать полные права на эту очередь ("rw") или хотя бы 'ro + move_into' то переместить заявку можно из любого интерфейса.

Сверяю вызовы функции для получения списка очередей:

AgentTicketZoom.pm

Code: Select all

    my %MoveQueues = $Self->{TicketObject}->MoveList(
        TicketID => $Self->{TicketID},
        UserID   => $Self->{UserID},
        Action   => $Self->{Action},
        Type     => 'move_into',
    );
TicketOverviewPreview.pm

Code: Select all

    my %MoveQueues = $Self->{TicketObject}->MoveList(
        TicketID => $Param{TicketID},
        UserID   => $Self->{UserID},
        Action   => $Self->{LayoutObject}->{Action},
        Type     => 'move_into',
    );
На вид, всё правильно, попытка заменить
Action => $Self->{LayoutObject}->{Action},
на конкретное значение
Action => 'AgentTicketZoom',
не дало положительных результатов. Состояние осталось прежним, если есть "rw" право, то видим очередь в списке для перемещения, если нет, то и переместить в эту очередь из превью нельзя.

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

Кому интересно можете посмотреть мои патчики в разделе Patches / Module.
Там я выложил только те из моих патчей, которые считаю особенно полезными и в принципе которые хотел бы видеть встроенные в новые версии OTRS.
Размещал их там, когда ещё не было русского раздела форума, поэтому и описание там на английском, но могу и русское описание дать, если заинтересует.

Извините за длинный пост. Краткость не моя сестра. :D
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

Думаю по второму вопросу проблему можно будет локализовать проще.
Поигравшись ещё немного с правами заметил, что у пользователя в списке перемещений в интерфейсе предварительного просмотра (Action=AgentTicketQueue&View=Preview) в списке перемещений заявок отображаются очереди, для которых у данного пользователя выставлены только права "ro". При этом те же очереди не отображаются в списке для перемещений при подробном рассмотрении заявки (Action=AgentTicketZoom).
Если попытаться переместить заявку в очередь доступную только для чтения из интерфейса просмотра очереди то система выдаст критическую ошибку, что и стоило ожидать.

фанкция GetAllQueues() которая в конечном счете вызывается для формирования массива очередей присваивает значение фильтра Type = 'ro' в том случае, если значение не определено.

Code: Select all

    my $Type   = $Param{Type}   || 'ro';
Странно...
я же вижу:

Code: Select all

        Type     => 'move_into',
Не верь глазам своим...
Хоть убей, пока не могу понять почему значение Type не доходит до адресата из модуля TicketOverviewPreview.pm
Искать причину нужно в функции перемычке MoveList() которая стоит на пути до целевой функции GetAllQueues().
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

Перепроверил $Param{Type} правильно добирается до функции GetAllQueues() в функции MoveList()...
Но тогда я в полном шоке. Почему вызовы одной и той же функции из разных мест дают разные результаты???...
alexus
Znuny wizard
Posts: 380
Joined: 20 Sep 2010, 16:54
Znuny Version: OTRS 6 CE
Real Name: Alexey Yusov
Company: Radiant System Group s.r.o
Location: Prague
Contact:

Re: Разграничение прав агентов по группам

Post by alexus »

Будем разбираться последовательно.
1. По поводу - "агент не видит заявок".
Дело не в правах, а в отображении заявок. Надо править с конфигурации. Там по умолчанию стоят права "rw". Как только вы их убираете - заявки становятся не видны.
Alexey Yusov

Production: OTRS CE ITSM 6.0.28 on CentOS 7 + Apache 2.4 + MariaDB 10.4.13 + Radiant Customer Portal

Radiant System OTRS Intergrator
RS4OTRS marketplace
Stay tuned on our Facebook
((OTRS)) Community Edition - what next?
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

ULiX wrote:Перепроверил $Param{Type} правильно добирается до функции GetAllQueues() в функции MoveList()...
Но тогда я в полном шоке. Почему вызовы одной и той же функции из разных мест дают разные результаты???...
Капнул ещё глубже...
Проверил значение $Param{Type} перед вызовом GetAllQueues(), в функции MoveList() прямо до строчки

Code: Select all

%Queues = $Self->{QueueObject}->GetAllQueues(%Param);
$Param{Type} = "move_into"
И тут же внутри функции GetAllQueues() уже $Param{Type} = 'ro'
Как это возможно, если массив %Param читается из поступивших аргументов?
my ( $Self, %Param ) = @_;

Я несколько обескуражен таким поведением... Откуда берется иное значение в момент вызова функции???. Impossible!!! Это ломает мои представления о программировании... Если только массив %Param где-то ещё не определен как глобальный...
Сейчас попробую заменить имя переменной.
alexus wrote:Будем разбираться последовательно.
1. По поводу - "агент не видит заявок".
Дело не в правах, а в отображении заявок. Надо править с конфигурации. Там по умолчанию стоят права "rw". Как только вы их убираете - заявки становятся не видны.
А можно подробнее, что именно в конфигах менять нужно?
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

alexus wrote:Будем разбираться последовательно.
1. По поводу - "агент не видит заявок".
Дело не в правах, а в отображении заявок. Надо править с конфигурации. Там по умолчанию стоят права "rw". Как только вы их убираете - заявки становятся не видны.
Большое спасибо за наводку!!!
Нашел!!!
Ticket::Frontend::AgentTicketQueue###ViewAllPossibleTickets:
Show all ro and rw queues in the QueueView (not only rw queues)?
Первый вопрос можно закрыть...
Остался второй... Он меня всё ещё напрягает.
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

Дополнения по второму вопросу.
Ещё немного изучил вопрос.
Ещё забавнее...
Параметр Action
при вызове MoveList()

Code: Select all

    my %MoveQueues = $Self->{TicketObject}->MoveList(
        TicketID => $Param{TicketID},
        UserID   => $Self->{UserID},
        Action   => $Self->{LayoutObject}->{Action},
        Type     => 'move_into',
    );
из модуля TicketOverviewPreview.pm прекрасно попадает в функцию MoveList но пропадает в функции GetAllQueues().

А при вызове MoveList() из AgentTicketZoom.pm никакие параметры не теряются, переданное значение Action наследуется как на уровне модуля
Ticket.pm функция MoveList() так и на уровне модуля Queue.pm функции GetAllQueues().

Странно... может стоит версию Perl обновить.
у меня сейчас используется
v5.8.8 built for x86_64-linux-thread-multi

Если бы я сам писал программу, то ни за что не заподозрил бы, что переданные мной аргументы функции как-то иначе воспримутся...

Подтвердите кто-нибудь присутствие данной проблемы. Может это только мне так повезло?
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

Решил немного поэкспериментировать.

Решил генерировать массив очередей без функции перемычки MoveList() напрямую:

Code: Select all

    my %MoveQueues = $Self->{QueueObject}->GetAllQueues(
        TicketID => $Param{TicketID},
        UserID   => $Self->{UserID},
        Action   => $Self->{LayoutObject}->{Action},
        Type     => 'move_into',
    ); 
Не помогло! :(
Я в полном шоке!!! Даже при таком прямом вызове на входе GetAllQueues параметр Action не определен, а Type равен 'ro'...
Но ведь это нереально!!! Так не должно быть!!!
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

Хм...
Оказалось что отчасти виноват в глюке я сам. Но причины всё равно не понятны...
Итак...
Фукция TicketListShow() модуля LayoutTicket.pm претерпела изменения в ходе моих патчей быстрой навигации, что и вызвало это недоразумение, однако я до сих пор не нашёл взаимосвязи...

В данной функции происходит вызов:

Code: Select all

    # run module
    my $Output = $Object->Run(
        %Param,
        Config    => $Backends->{$View},
        Limit     => $Limit,
        StartHit  => $StartHit,
        PageShown => $PageShown,
        AllHits   => $Param{Total} || 0,
    );
Который собственно вызывает функции new() модуля TicketOverviewPreview.pm
Далее из этой функции вызывается функия _Show для каждого тикета в очереди:

Code: Select all

            my $Output = $Self->_Show(
                TicketID => $TicketID,
                Counter  => $CounterOnSite,
                Bulk     => $BulkFeature,
                Config   => $Param{Config},
            );
И уже в функции _Show имеем вызов MoveList()

Так вот для реализации ListBox со спсиком очередей для быстрого перехода между очередями я до вызова $Object->Run() уже один раз вызываю напрямую функцию
my %AllQueues = $Self->{QueueObject}->GetAllQueues(UserID => $Self->{UserID}, Type => 'ro');

Вот если эту строчку убрать, то всё будет бачить нормалёк.
При этом абсолютно не важно какое имя для массива будет определено %AllQueues или %MySpeedNavQueues, важен сам факт вызова функции.
После его первого вызова происходит сохранение результата механизмом кеширования самой OTRS (реализован в функции GetAllQueues) и повторные вызовы уже не делают запросы в базу данных и не извлекают список очередей по новой, а просто читают предыдущий результат из внутреннего кэша OTRS.

В итоге имеем такой вот глюк...

Теперь уже понятно в каком направлении копать. Посмотрю как можно обойти кеширование, либо придется реализовать дубль функции GetAllQueues() только без механизма кеширования.

Спасибо всем за содействие и сочувствие. :)
Хорошая была зарядка для мозгов.
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

Хотя...
Я вот подумал...
А ведь это неправильно!!!
Значение в кеше привязано только по UserID

Code: Select all

$Self->{"QG::GetAllQueues::UserID::$Param{UserID}"} = \%MoveQueues;
Т.е. если время жизни кеша не вышло, то функцию абсолютно не волнует, что параметры запроса изменились и ответ должен быть иным!
Это не верно! Если уже тогда кешировать то по всем параметрам:
UserID and Type;
CustomerUserID and Type;
В конечном счете результат из базы зависит именно от этих пар параметров.
alexus
Znuny wizard
Posts: 380
Joined: 20 Sep 2010, 16:54
Znuny Version: OTRS 6 CE
Real Name: Alexey Yusov
Company: Radiant System Group s.r.o
Location: Prague
Contact:

Re: Разграничение прав агентов по группам

Post by alexus »

Задайте Ваш вопрос на OTRS.ru. Может там помогут.
А про отображение заявок, я рад что помогло :-))).
Alexey Yusov

Production: OTRS CE ITSM 6.0.28 on CentOS 7 + Apache 2.4 + MariaDB 10.4.13 + Radiant Customer Portal

Radiant System OTRS Intergrator
RS4OTRS marketplace
Stay tuned on our Facebook
((OTRS)) Community Edition - what next?
ULiX
Znuny newbie
Posts: 16
Joined: 07 Jul 2010, 23:04
Znuny Version: 2.4.7

Re: Разграничение прав агентов по группам

Post by ULiX »

С проблемой справился.
Сразу после чтения списка очередей для своего быстрого навигатора установил очистку кеша:

my %AllQueues = $Self->{TicketObject}->MoveList(UserID => $Self->{UserID},Type => 'ro',Action => $Env->{Action},);
$Self->{QueueObject}->{"QG::GetAllQueues::UserID::$Self->{UserID}"} = undef;

Ну а по хорошему, конечно нужно связать кеш с двумя параметрами вместо одного в функции GetAllQueues().
Locked