Как разграничивать права на уровне бизнес-логики хранимых процедур

Введение

В стандартном варианте разграничение доступа осуществляется на основе ролей (admin, manager, operator и др.). Каждый компонент через настройки задает доступ по ролям (поле Роли). 

Но иногда требуется более точное, детальное разграничение доступа (например пользователь роли manager может иметь доступ только к определенным проектам, а не всем подряд).

Подход распределение доступа через наличие права у пользователя

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

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

Это упростит дальнейшее изменение логики проверки доступа (например, добавилась новая роль, изменена логика проверки для отдельных пользователей и т.д.).

Пример функции для сущности Проект. Мы проверяем по определенному праву доступа к целому проекту, а не к каждой отдельной части проекта - к тикету, к логам проекта и т.д.

ALTER    FUNCTION [dbo].[sec_project_hasRight]  (
            @itemID int,
            @username nvarchar(128),
            @right nvarchar(128)
)
RETURNS bit
AS
BEGIN
            declare @res bit = 0
            -- для каждого права делаем свою бизнес логику проверки на основе itemID и username
            if(@right in ('readBug', 'editBug') ) begin  
                        if( ...  CONDITION - HAS USER THIS RIGHT? ... ) begin
                                   set @res = 1
                        end
            end

            if(@right in ('manageBugChecklist') ) begin  
                        if( ...  CONDITION - HAS USER THIS RIGHT? ... ) begin
                                   set @res = 1
                        end
            end
            --- ...
   RETURN  @res
END

 В компонентах мы вначале проверяем доступ. Если нет определенного права, то выдаем сообщение об ограничении доступа (или редирект) 

if([dbo].[sec_project__hasRight](@itemID, @username, 'editDocs=')=0 ) begin
    	select 0 Result, 'No access' Msg
        return
end

Примечание:

Страница-источник на сайте falconspace.ru