Получение уровня доступа заданного пользователя ко всем объектам БД Лоцман

Автор 1ndifferent, 24.05.18, 10:30:27

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

1ndifferent

Форумчане, доброго времени суток.
Возникла задачка получить отчет о доступе конкретного пользователя ко всем доступным ему проектам в БД.

Сначала пробовал получить список всех доступных объектов из БД через FindObjects
А затем перебор всех объектов с получением списка доступов на каждый из них и сравнение с текущим пользователем.
Работает, но это оооочень долго.

Пробовал напрямую лезть в БД:
Есть таблица Priviliges, в которой записан только директивный доступ к определенным объектам.
Есть еще несколько таблиц, в которых записан доступ по умолчанию для групп пользователей из конфигуратора.
Я правильно понимаю, что Лоцман, при вычислении доступа к конкретного пользователя пользуется всеми этими таблицами?
Т.е. сначала считывается перечень ролей пользователя, потом доступ к объектам для этих ролей, а потом делается, ну предположим Right Join с таблицей, в которой записаны директивные доступы?

Может кто сталкивался с подобной задачей, поделитесь мыслями.

Chipollino

Во-первых, непонятно кто будет запускать отчёт - сам пользователь будет смотреть свои права или начальник (администратор) будет смотреть по любому пользователю

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

Если пытаться строить запрос в SQL, то учтите, что директивные права пользователя на объект перекрывают любые другие.
Если их нет, то директивные права группы в которую он входит (если нескольким группам назначены директивные права, то максимальные из них)
Если директивные права ни для пользователя, ни для групп не назначены, то будет минимальное право из пары Тип-Состояние (например на "деталь" минимальные права "Чтение-запись", а состояние "Утверждён" - только чтение, то деталь в состоянии утверждён будет доступна только на чтение)

А так же учитывайте то, что у директивных прав может быть срок действия, после которого они в таблицах будут видны, но уже не действуют
+ Благодарностей: 1

1ndifferent

Большое спасибо за развернутый ответ. Узнал для себя много нового по расчету прав доступа.

Нашел решение, возможно кому-то будет интересно:

Немного полазив по БД нашел функции fnAccessLevel и fnAccessLevel1, которые судя по всему, полностью решают поставленную передо мной задачу. На вход принимает ID пользователя, дату создания объектов с которой возвращать значение и параметр Label (не используется). На выходе функция выдает табличку с доступам ко всем объектам БД, к которым пользователя допущен и не допущен.
Дальше можно уже отфильтровать по уровню доступа и посмотреть.

Chipollino

Честно говоря не знаю, как именно работает эта функция, но если собирать самому запрос из таблиц получается примерно так:


DECLARE
@dtToday datetime = SYSDATETIME(), -- время запуска, для таблицы директивных прав
@inIdUser int, -- ID пользователя
@stUserName varchar(255) = 'UserLogin';  -- Логин пользователя по которому ведётся поиск (для Windows-аутентификации - Domain\Login)

SET @inIdUser = (SELECT TOP 1 [inIdUser] FROM [vwUsersInGroups] WHERE [stUserName] = @stUserName)

DECLARE @Rights TABLE( _ID_VERSION int, _PRODUCT varchar(255), _TYPE varchar(255), _STATE varchar(255), _VERSION varchar(255), _ACCESSLEVEL int );

INSERT INTO @Rights
SELECT
   [rvwVersions].[id]      _ID_VERSION
  ,[rvwVersions].[product] _PRODUCT
  ,[rvwVersions].[type]    _TYPE
  ,[rvwVersions].[state]   _STATE
  ,[rvwVersions].[version] _VERSION
  ,CASE
     WHEN ([UserPrivs].[_UserPrivs] IS NOT NULL) THEN([UserPrivs].[_UserPrivs])
     WHEN ([GroupPrivs].[_GroupPrivs] IS NOT NULL) THEN([GroupPrivs].[_GroupPrivs])
     WHEN ([Types].[inLevelDefault] <= [States].[inLevelDefault]) THEN ([States].[inLevelDefault])
     WHEN ([Types].[inLevelDefault] > [States].[inLevelDefault]) THEN ([Types].[inLevelDefault])
     ELSE (NULL)
    END AS _ACCESSLEVEL
  FROM [rvwVersions]
LEFT JOIN ( -- Максимальные права групп на тип
SELECT [inIdType], MAX(inLevelDefault) [inLevelDefault] FROM [rlTypesAndUserGroups]
  JOIN [vwUsersInGroups] ON [rlTypesAndUserGroups].[inIdUserGroup] = [vwUsersInGroups].[inIdGroup] AND [vwUsersInGroups].[inIdUser] = @inIdUser
  WHERE [inLevelDefault] > 0
  GROUP BY [inIdType] ) [Types] ON [rvwVersions].[idtype] = [Types].[inIdType]
LEFT JOIN ( -- Максимальные права групп на состояние
SELECT [inIdState], MAX(inLevelDefault) [inLevelDefault] FROM [rlStatesAndUserGroups]
  JOIN [vwUsersInGroups] ON [rlStatesAndUserGroups].[inIdUserGroup] = [vwUsersInGroups].[inIdGroup] AND [vwUsersInGroups].[inIdUser] = @inIdUser
  WHERE [inLevelDefault] > 0
  GROUP BY [inIdState] ) [States] ON [rvwVersions].[idstate] = [States].[inIdState]
LEFT JOIN ( -- Директивные права пользователя на объект
SELECT [stPrivileges].[inIdVersion], [stPrivileges].[inLevel] _UserPrivs FROM [stPrivileges] 
  JOIN [vwUsersInGroups] ON [vwUsersInGroups].[inIdUser] = @inIdUser AND [stPrivileges].[inIdUser] = [vwUsersInGroups].[inIdUser] -- Права на конкретного пользователя
  ) [UserPrivs] ON [rvwVersions].[id] = [UserPrivs].[inIdVersion]
LEFT JOIN ( -- Директивные права группы на объект
SELECT [stPrivileges].[inIdVersion], MAX([stPrivileges].[inLevel]) _GroupPrivs FROM [stPrivileges] 
  JOIN [vwUsersInGroups] ON [vwUsersInGroups].[inIdUser] = @inIdUser AND [stPrivileges].[inIdUser] = [vwUsersInGroups].[inIdGroup] -- на любую группу куда он входит
  GROUP BY [stPrivileges].[inIdVersion]
) [GroupPrivs] ON [rvwVersions].[id] = [GroupPrivs].[inIdVersion]

 
SELECT TOP 100 * FROM @Rights
WHERE _ACCESSLEVEL IS NOT NULL


Цитата: Chipollino от 24.05.18, 17:39:16
Если их нет, то директивные права группы в которую он входит (если нескольким группам назначены директивные права, то максимальные из них)
Тут ошибся, назначаться будут минимальные из них.
Всё же правильно будет "максимальные" из директивно назначенных, но это, почему-то, не касается папок. Там всё наоборот - на папку будут минимальные. Так что код работает не до конца
+ Благодарностей: 1

dosymep

Я бы посмотрел в сторону метода GetInfoAboutVersionsPrivileges2, он возвращает набор данных содержащий назначенные директивные права на объект, потом в этом наборе данных найдите пользователя.
Этому методу передается список идентификаторов перечисленных через запятую (id1,id2,id3,id4)