Известно, что в системе DIRECTUM принцип назначения прав на справочники принципиально отличается от назначения прав на электронные документы. Если права на документы назначаются на каждый объект независимо, то права на записи справочника назначаются следующими механизмами:
Разумной комбинацией этих механизмов можно решить достаточно большой спектр задач, но порой их все же бывает недостаточно.
Приведу пример. В организации холдингового типа есть несколько бэк-офисов. Каждый из бэк-офисов должен иметь права доступа на те записи справочника «Договоры», которые относятся к его компетенции. На первый взгляд, это решается фильтраторами. Но на деле оказывается, что однозначно определить фильтратор для записей нельзя, т.к. часть договоров пересылается между подразделениями, находящимися в разных дочерних организациях и, соответственно, в компетенции разных бэк-офисов. Т.е. определить уровень доступа сотрудников бэк-офиса к записи справочника можно только исходя из пути следования пакета документов. С технической точки зрения, можно было бы ввести фильтратор по компетенциям и добавлять эти компетенции в табличную часть в типовом маршруте. Но документ могут переслать и обычной подзадачей, поэтому такой способ в общем случае не подходит. В этом случае можно наследовать права на запись справочника от электронного документа. При открытии справочника проверяются права доступа на компоненту, реквизиты, применяются фильтраторы. Но кроме этого, на SQL-запрос, получающий записи справочника, накладываются дополнительные ограничения.
User = EDocuments.CurrentUser
AddWhere = Format('
(exists (select 1
from
SBEDoc EDocuments,
SBEDocAcc AccessRights,
[dbo].SBFullAccessRights RightsAs
where
AccessRights.EDocID = MBAnalit.Point3
and AccessRights.EDocID = EDocuments.XRecID
and AccessRights.AccountID = RightsAs.UserOrGroupID
and RightsAs.UserID = %0:s))'; User.ID)
СпрИзмНабДан(;; AddWhere)
Этот код следует поместить в событие «Набор данных открытие». Point3 – имя поля реквизита Ссылка3, в котором хранится ИД документа, от которого запись справочника наследует права. В нашем случае это ИД договорного документа. Теперь пользователи будут видеть только те записи справочника, у которых в реквизите Ссылка3 находится ИД документа, на который у этих пользователей есть права. Соответственно, если документ пересылают в другое подразделение и выдают на него права, то права на запись справочника это подразделение получает автоматически.
Подобным образом можно организовать проверки прав практически любой сложности. Надо только учитывать, что чем больше критериев вы добавите к набору данных, и чем они будут сложнее, тем медленнее будет выполняться операция открытия справочника. Поэтому к созданию подобных запросов стоит подходить с умом.
Более сложный пример – нужно ограничить права доступа на справочник только тем работникам, которые указаны в записи справочника, как в главном разделе, так и в нескольких табличных. Решается сходным образом – через добавление критериев к набору данных.
User = EDocuments.CurrentUser
AddWhere = Format('%s in (select
AccRights.UserID
from
MBAnalit Empl,
SBFullAccessRights AccRights
where
AccRights.UserOrGroupID = Empl.Polzovatel and
Empl.Vid =%s and
(Empl.Analit = MBAnalit.FIO or
Empl.Analit = MBAnalit.FIO2 or
Empl.Analit = MBAnalit.FIO3 or
Empl.Analit in (select Table1.FIOT from MBAnValR Table1
where Table1.Analit = MBAnalit.Analit and Table1.FIOT is not null) or
Empl.Analit in (select Table2.FIOT2 from MBAnValR2 Table2
where Table2.Analit = MBAnalit.Analit and Table2.FIOT2 is not null) or
Empl.Analit in (select Table3.FIOT3 from MBAnValR3 Table3
where Table3.Analit = MBAnalit.Analit and Table3.FIOT3 is not null)))';
ArrayOf(User.ID; ИДТипСпр('РАБ')))
СпрИзмНабДан(;; AddWhere)
В данном запросе мы разрешаем доступ к записи справочника тем работникам, которые указаны в трех реквизитах карточки и трех детальных разделах (реквизиты FIO
И последняя «вкусность» - в обоих запросах учитывается замещение пользователей. Т.е. права получат не только те, кто явно указан в соответствующих реквизитах, но и все, кто их замещает. Для этого используется полезная автоформируемая табличка SBFullAccessRights. Эта таблица обновляется при каждом заходе пользователя в DIRECTUM и именно с ее помощью IS-Builder проверяет права на документы с учетом замещения и вхождения пользователей в группы. Например, вот как из нее можно определить, замещает ли один пользователь другого (глубина замещения роли не играет). Результат «1» означает, что пользователь замещает другого:
select 1 from SBFullAccessRights
where UserID = <ИД замещающего пользователя> and UserOrGroupID = <ИД замещаемого пользователя>
Все это работает для DIRECTUM 4.5.x – 4.6.х. А также будет работать и для еще только готовящейся версии 4.7.
Разумной комбинацией этих механизмов можно решить достаточно большой спектр задач, но порой их все же бывает недостаточно.
Приведу пример. В организации холдингового типа есть несколько бэк-офисов. Каждый из бэк-офисов должен иметь права доступа на те записи справочника «Договоры», которые относятся к его компетенции. На первый взгляд, это решается фильтраторами. Но на деле оказывается, что однозначно определить фильтратор для записей нельзя, т.к. часть договоров пересылается между подразделениями, находящимися в разных дочерних организациях и, соответственно, в компетенции разных бэк-офисов. Т.е. определить уровень доступа сотрудников бэк-офиса к записи справочника можно только исходя из пути следования пакета документов. С технической точки зрения, можно было бы ввести фильтратор по компетенциям и добавлять эти компетенции в табличную часть в типовом маршруте. Но документ могут переслать и обычной подзадачей, поэтому такой способ в общем случае не подходит. В этом случае можно наследовать права на запись справочника от электронного документа. При открытии справочника проверяются права доступа на компоненту, реквизиты, применяются фильтраторы. Но кроме этого, на SQL-запрос, получающий записи справочника, накладываются дополнительные ограничения.
User = EDocuments.CurrentUser
AddWhere = Format('
(exists (select 1
from
SBEDoc EDocuments,
SBEDocAcc AccessRights,
[dbo].SBFullAccessRights RightsAs
where
AccessRights.EDocID = MBAnalit.Point3
and AccessRights.EDocID = EDocuments.XRecID
and AccessRights.AccountID = RightsAs.UserOrGroupID
and RightsAs.UserID = %0:s))'; User.ID)
СпрИзмНабДан(;; AddWhere)
Этот код следует поместить в событие «Набор данных открытие». Point3 – имя поля реквизита Ссылка3, в котором хранится ИД документа, от которого запись справочника наследует права. В нашем случае это ИД договорного документа. Теперь пользователи будут видеть только те записи справочника, у которых в реквизите Ссылка3 находится ИД документа, на который у этих пользователей есть права. Соответственно, если документ пересылают в другое подразделение и выдают на него права, то права на запись справочника это подразделение получает автоматически.
Подобным образом можно организовать проверки прав практически любой сложности. Надо только учитывать, что чем больше критериев вы добавите к набору данных, и чем они будут сложнее, тем медленнее будет выполняться операция открытия справочника. Поэтому к созданию подобных запросов стоит подходить с умом.
Более сложный пример – нужно ограничить права доступа на справочник только тем работникам, которые указаны в записи справочника, как в главном разделе, так и в нескольких табличных. Решается сходным образом – через добавление критериев к набору данных.
User = EDocuments.CurrentUser
AddWhere = Format('%s in (select
AccRights.UserID
from
MBAnalit Empl,
SBFullAccessRights AccRights
where
AccRights.UserOrGroupID = Empl.Polzovatel and
Empl.Vid =%s and
(Empl.Analit = MBAnalit.FIO or
Empl.Analit = MBAnalit.FIO2 or
Empl.Analit = MBAnalit.FIO3 or
Empl.Analit in (select Table1.FIOT from MBAnValR Table1
where Table1.Analit = MBAnalit.Analit and Table1.FIOT is not null) or
Empl.Analit in (select Table2.FIOT2 from MBAnValR2 Table2
where Table2.Analit = MBAnalit.Analit and Table2.FIOT2 is not null) or
Empl.Analit in (select Table3.FIOT3 from MBAnValR3 Table3
where Table3.Analit = MBAnalit.Analit and Table3.FIOT3 is not null)))';
ArrayOf(User.ID; ИДТипСпр('РАБ')))
СпрИзмНабДан(;; AddWhere)
В данном запросе мы разрешаем доступ к записи справочника тем работникам, которые указаны в трех реквизитах карточки и трех детальных разделах (реквизиты FIO<x> и FIOT<x>). Важная деталь – в проверке участвуют только те работники, у которых указаны пользователи (иначе нельзя сравнить их с текущим пользователем).
И последняя «вкусность» - в обоих запросах учитывается замещение пользователей. Т.е. права получат не только те, кто явно указан в соответствующих реквизитах, но и все, кто их замещает. Для этого используется полезная автоформируемая табличка SBFullAccessRights. Эта таблица обновляется при каждом заходе пользователя в DIRECTUM и именно с ее помощью IS-Builder проверяет права на документы с учетом замещения и вхождения пользователей в группы. Например, вот как из нее можно определить, замещает ли один пользователь другого (глубина замещения роли не играет). Результат «1» означает, что пользователь замещает другого:
select 1 from SBFullAccessRights
where UserID = <ИД замещающего пользователя> and UserOrGroupID = <ИД замещаемого пользователя>
Все это работает для DIRECTUM 4.5.x – 4.6.х. А также будет работать и для еще только готовящейся версии 4.7.
"вкусность" особенно хороша!
есть какие-то советы/ориентировки по тому, насколько сильно такие расчеты могут замедлять открытие справочников?
Например - на 1000 записей справочника - дополнительная задержка от ... до ... сек., или процентов? Или - мы не особенно почувствуем замедления на клиенте, на фоне того, что само открытие справочника - процесс не самый быстрый?
Точные цифры можно получить только на реальном запросе и реальной системе. К примеру, первое ограничение (наследование прав от документа) замедляет выполнение запроса к справочнику из 1000 записей на 200 мс. Вроде бы, немного, но при этом замедление составляет 300%.
Да, сам запрос не всегда является львиной долей затраченного на открытие справочника времени. Обычно тормозит клиент, а не сервер.
Кроме того, запросы относительно несложно оптимизируются добавлением нужных индексов в таблицы. При правильной индексации влияние таких ограничений на время выполнения запроса можно очень сильно уменьшить. Возможно, напишу еще материал по индексации - есть под рукой один весьма показательный примерчик.
Авторизуйтесь, чтобы написать комментарий