Показать сообщение отдельно
Старый 13.03.2008, 17:41   #11  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
SysRecordLevelSecurityWizard: Настройка RLS для неотображаемой таблицы
ПРОБЛЕМА:

Необходимо для заданной группы прав настроить RLS на таблицу "Коды журналов ОС", которой нет в списке таблиц, отображаемых в Мастере. Таблица "Коды журналов ОС" в нашем сильноэксклюзивном приложении от компании GMCS называется GM_RAssetJournalName.

РЕЦЕПТ:

1. Открываем форму "Доступ на уровне записей" (SysRecordLevelSecurity), до которой предварительно добираемся по меню Ax 3.0: Администрирование \Настройки \Контроль доступа \Доступ на уровне записей.

2. Находясь в гриде, жмем Ctrl+N и создаем при помощи Мастера запись для заданной группы и какой-нибудь произвольной таблицы, которая нам не нужна, но которая видна в списке Мастера, например, "Модели учета" - RAssetStandardTable (она видна в раскрытом узле "СНГ Основные средства" после включения опции "Показать все таблицы").

3. Закончив шаги Мастера, выходим из формы "Доступ на уровне записей", не настраивая для созданной записи никаких фильтров (т.е. не пользуемся кнопкой "Запрос").

4. В таблице SysRecordLevelSecurity в нужной записи меняем код "ненужной" таблицы на код требуемой таблицы любым удобным способом - вручную (через Обозреватель таблицы или средствами СУБД) или при помощи элементарного джоба:
X++:
static void Job_UpdateRLSrecord(Args _args)
{
    SysRecordLevelSecurity sysRLS;
    ;
    ttsbegin;

    select forupdate sysRLS
        where sysRLS.companyId == curExt()
           && sysRLS.groupId == '<наша группа прав>'
           && sysRLS.tabId == tablenum(RAssetStandardTable);

    sysRLS.tabId = tablenum(GM_RAssetJournalName);
    sysRLS.update();

    ttscommit;
}
5. Снова открываем форму "Доступ на уровне записей", находим нужную запись - видим в колонке "Название таблицы", что таблица благополучно поменялась.

6. Нажимаем кнопку "Запрос" и выполняем требуемую настройку фильтра для нашей таблицы.

7. "Захардкодиваем" код нашей таблицы в метод buildTableTree формы SysRecordLevelSecurityWizard. Это необходимо для того, чтобы возможные последующие настройки RLS для данной группы прав не снесли нашу, с таким трудом вживленную, таблицу. Для этого меняем условие в IF - тупо, зато быстро, расширяя его на ИЛИ с нашей таблицей:
c
X++:
if (dictTable &&
    dictTable.allowSecuritySetup() &&
    (dictTable.tableGroup() == TableGroup::Main ||
     tableSelection.selection() ||
     tableIds.in(tableId)) &&
     (domainAccess || SysRecordLevelSecurityWizard::tableAllowed(tableId)))
на
X++:
if (
   (dictTable &&
    dictTable.allowSecuritySetup() &&
    (dictTable.tableGroup() == TableGroup::Main ||
     tableSelection.selection() ||
     tableIds.in(tableId)) &&
     (domainAccess || SysRecordLevelSecurityWizard::tableAllowed(tableId)))
   ||
   tableId == tablenum(GM_RAssetJournalName)
   )
Подобным образом надо будет расширять условие при добавлении в RLS каждой новой неотображаемой таблицы. Если таких таблиц станет много и надоест каждый раз править метод, то, может, будет иметь смысл вставить в условие глобальный макрос, расширяемый по мере необходимости, или читать коды "исключительных" таблиц из какой-нибудь специальной настроечной таблицы.

ИСТОЧНИКИ (ВДОХНОВЕНИЯ):

Еще по поводу QueryBuildRange()
Коды аналитики