Права доступа на реквизиты сложных карточек документов или справочников

6 2

Когда встаёт вопрос о доступности тех или иных реквизитов карточки документа или справочника для разных пользователей или групп пользователей, то реализовать такое ограничение, как правило, несложно. Достаточно написать несколько блоков if...else...endif, в которых включаются/выключаются нужные реквизиты. Достаточно обыденная задача для простых карточек и несложных условий. Но мы рассмотрим сложный случай - когда имеются более сотни реквизитов на карточке справочника документа, куча участников бизнес-процесса и множество условий, определяющих каким участникам процесса какие реквизиты карточки и при каких условиях должны быть доступны.

Когда появилась такая задача, то встал выбор - или писать несколько экранов кода (пару-тройку, если не больше), в которых будут всяческие проверки разных условий, с включениями/отключениями групп реквизитов, которые к тому же частично пересекаются друг с другом, или придумать что-то, что позволит не погрязнуть в дебрях кода. Поэтому была придумана функция, для которой формируется список прав доступа по реквизитам, формирующийся на основании следующих данных:

  • Участники - список пользователей или групп пользователей или констант (в которых указаны группы пользователей), для которых производится проверка прав доступа к реквизитам карточки. Может состоять из одного пользователя/группы/константы.
  • Реквизиты - список реквизитов карточки, которые должны быть включены/выключены по итогам вычисления условий доступа для пользователя или группы пользователей.
  • Условия доступа - массив условий проверки доступа. В зависимости от суммы всех условий доступа вычисляется дать или не дать участнику доступ к реквизитам. (подробное описание указано в справке к функции)

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

Пример кода (событие открытия записи):

    // Первая группа реквизитов
    RequisiteList1 = 'Requisite1|Requisite2|Requisite3|Requisite4|Requisite5|Requisite6|Requisite7|Requisite8|Requisite9'
    // Вторая группа реквизитов
    RequisiteList2 = 'Requisite10|Requisite11|Requisite12|Requisite13|Requisite14|Requisite15|Requisite16|Requisite17|Requisite18'    
    // Третья группа реквизитов
    RequisiteList3 = 'Requisite19|Requisite20|Requisite21|Requisite22|Requisite23|Requisite24|Requisite25|Requisite26|Requisite27'      
    // Четвертая группа реквизитов
    RequisiteList4 = 'Requisite28|Requisite29|Requisite30|Requisite31|Requisite32|Requisite33|Requisite34|Requisite35|Requisite36'      
                   
    // Первое условие доступа. Проверка стадии ЖЦ -(стадия ЖЦ не установлена или = Initialization или = Revision)
    Condition1 = ArrayOf('ISBEDocLifeStageName'; '|Initialization|Revision'; TRUE)  
    // Второе условие доступа. Проверка установленной галочки на карточке документа
    Condition2 = ArrayOf('RequisiteCheck'; 'Да'; TRUE)
    // Третье условие доступа. Проверка стадии ЖЦ
    Condition3 = ArrayOf('ISBEDocLifeStageName'; 'Agreement'; TRUE)
    // Четвертое условие доступа. Проверка стадии ЖЦ
    Condition4 = ArrayOf('ISBEDocLifeStageName'; 'Completed'; TRUE)
    // Пятое условие доступа. Проверка пользователя
    CondCurrentUserIsAuthor = ArrayOf('ISBEDocAuthor'; Trim(EDocuments.CurrentUser.Code); TRUE)      
    
    // Создание списка прав доступа
    AccessReqList = CreateList()
    
    // Установка прав доступа к реквизитам для автора документа
    AuthorCode = Object.ISBEDocAuthor
    AuthorName = ServiceFactory.GetUserByCode(AuthorCode).Name
    Author = 'ПОЛ:' & AuthorName
 
    // Предоставить автору доступ к реквизитам RequisiteList1
    // если стадия ЖЦ не установлена или = Initialization или = Revision
    AccessReqList.Add(''; ArrayOf(Author; RequisiteList1; ArrayOf(Condition1)))
    // Выдача автору прав на ещё одну часть реквизитов, если установлена галочка RequisiteCheck
    // и стадия ЖЦ не установлена или = Initialization или = Revision
    AccessReqList.Add(''; ArrayOf(Author; RequisiteList2; ArrayOf(Condition1; Condition2)))
    // Выдача прав автору на установку галочки RequisiteCheck, если он входит в группу UserGroup1
    // и стадия ЖЦ не установлена или = Initialization или = Revision
    AccessReqList.Add(''; ArrayOf('КОНСТ:Group1CodeConst'; 'RequisiteCheck'; ArrayOf(Condition1; CondCurrentUserIsAuthor)))
        
    // Выдача прав на группы реквизитов RequisiteList2 и RequisiteList3 пользователю,
    // если он входит в группу UserGroup2 и стадия ЖЦ = Agreement
    AccessReqList.Add(''; ArrayOf('КОНСТ:Group2CodeConst'; RequisiteList2 & '|' & RequisiteList3; ArrayOf(Condition3)))
    // Выдача прав на группу реквизитов RequisiteList4 пользователю,
    // если он входит в группу UserGroup3 и стадия ЖЦ = Completed
    AccessReqList.Add(''; ArrayOf('ГПЛ:UserGroup3'; RequisiteList4; ArrayOf(Condition4)))    
    // Выдача прав доступа на все реквизиты определённому пользователю
    // если стадия ЖЦ = Agreement или = Completed
    FullReqList = RequisiteList1 & '|' & RequisiteList2 & '| ' & RequisiteList3 & '|' & RequisiteList4
    AccessReqList.Add(''; ArrayOf('ПОЛ:ResponsibleUser'; FullReqList; ArrayOf(Condition3)))
    AccessReqList.Add(''; ArrayOf('ПОЛ:ResponsibleUser'; FullReqList; ArrayOf(Condition4)))
    
    // Установка прав
    SetCardReqAccess(Object; AccessReqList)  

Каждый массив списка AccessReqList является элементом списка прав доступа. Для всех элементов списка прав доступа формируется единый список реквизитов, на каждый из которых рассчитывается доступ к нему.

Условия проверки элемента списка (если условий проверки несколько) объединяются логической операцией AND. Т.е. чтобы пользователь получил доступ к указанному списку реквизитов - должны выполниться все указанные условия. Пример:

AccessReqList.Add(''; ArrayOf('КОНСТ:Group1CodeConst'; 'RequisiteCheck'; ArrayOf(Condition1; CondCurrentUserIsAuthor)))

В данном случае устанавливается следующее правило доступа: Если пользователь входит в группу пользователей, указанную в константе Group1CodeConst и выполняются одновременно оба условия - Condition1 и CurrentUserIsAuthor, то пользователь получает доступ к установке галочки RequisiteCheck. Если автор документа не входит в эту группу, то доступа к галочке он не получит.

Если требуется указать права доступа, объединённые логической операцией OR, для одного и того же пользователя/группы и одного и того же набора реквизитов нужно указывать несколько записей прав доступа с разными условиями. Пример:

    // Выдача прав доступа на все реквизиты определённому пользователю
    // если стадия ЖЦ = Agreement или = Completed
    FullReqList = RequisiteList1 & '|' & RequisiteList2 & '| ' & RequisiteList3 & '|' & RequisiteList4
    AccessReqList.Add(''; ArrayOf('ПОЛ:ResponsibleUser'; FullReqList; ArrayOf(Condition3)))
    AccessReqList.Add(''; ArrayOf('ПОЛ:ResponsibleUser'; FullReqList; ArrayOf(Condition4)))

В данном случае права на реквизиты будут выданы в том случае, если выполняется условие Condition3 или условие Condition4 (хотя то же самое можно сделать и одним элементом списка прав доступа, объединив условия Condition3 и Condition4 в одно условие, т.к. они проверяют один и тот же реквизит - ISBEDocLifeStageName). Правило объединения прав доступа логической операцией OR распространяется, фактически, только на список реквизитов. Если разным группам пользователей указываются права на пересекающиеся списки реквизитов, то для реквизитов, относящихся к обоим спискам, итоговый доступ рассчитывается как сумма прав доступа по всем условиям списка, где этот реквизит встречается.

Полный список прав доступа задаётся при открытии записи. Для переключения доступности реквизитов при работе с карточкой (в событиях изменения значений реквизитов) достаточно использовать только те элементы списка прав доступа, которые влияют на те реквизиты, доступность которых зависит от того реквизита, значение которого изменяется.

Переключение доступности реквизитов, не зависящее от прав доступа (например, если реквизит А = 5, то реквизит Б всегда неактивен) следует осуществлять после вызова функции SetCardReqAccess.
 

Исходники функции: SetCardReqAccess.zip (6,26 Кб)

6
Авторизуйтесь, чтобы оценить материал.
1
Ирина Иващенко

Как это работает в случае замещения пользователя?

Александр Куклин

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

Авторизуйтесь, чтобы написать комментарий