Предположим, что система, в которой People
имеет доступ к Buildings
, а в зданиях, имеет доступ к определенным Rooms
.
Доступ определяется в соответствии с соответствующими таблицами Permissions
или в случае людей с полным доступом - полный доступ.
Таблицы БД определены следующим образом:
buildings (id INT)
rooms (id INT, building_id INT)
people (id INT, has_full_access BIT)
building_permissions (building_id INT, person_id INT)
room_permissions (room_id INT, person_id INT)
В настоящее время у меня есть функции с табличными значениями, которые возвращают таблицы с авторизованными идентификаторами зданий и комнат на основе идентификатора человека и наличия у него полного доступа.
CREATE FUNCTION fn_get_authorised_buildings (@person_id INT, @has_full_access BIT)
RETURNS TABLE AS
RETURN
(
SELECT b.id
FROM buildings b
WHERE @has_full_access = 1
UNION
SELECT b.id
FROM buildings b
INNER JOIN building_permissions bp ON bp.building_id = b.id
WHERE bp.person_id = @person_id
);
CREATE FUNCTION fn_get_authorised_rooms (@person_id INT, @has_full_access BIT)
RETURNS TABLE AS
RETURN
(
SELECT r.id
FROM rooms r
WHERE @has_full_access = 1
UNION
SELECT r.id
FROM rooms r
INNER JOIN room_permissions rp ON rp.room_id = r.id
WHERE rp.person_id = @person_id
);
Во всей системе, когда речь идет о зданиях и комнатах, мне нужно фильтровать эти таблицы на основе разрешений этого человека. Если у пользователя есть полный доступ, должны быть включены все строки, в противном случае - только те, для которых у него есть разрешение.
Мои запросы (упрощенно) выглядят примерно так:
DECLARE @person_id INT = 123
DECLARE @has_full_access BIT = 1
DECLARE @authorised_buildings TABLE (id INT)
INSERT INTO @authorised_buildings SELECT id FROM fn_get_authorised_buildings(@person_id , @has_full_access)
DECLARE @authorised_rooms TABLE (id INT)
INSERT INTO @authorised_rooms SELECT id FROM fn_get_authorised_rooms(@person_id, @has_full_access)
--Example A
SELECT *
FROM buildings b
INNER JOIN rooms r ON r.building_id = b.id
WHERE 1 = 1
AND b.id IN (SELECT id FROM @authorised_buildings)
AND r.id IN (SELECT id FROM @authorised_rooms)
--Example B
SELECT *
FROM floors f -- or other tables that are related to rooms
INNER JOIN rooms r ON r.floor_id = f.id
WHERE 1 = 1
AND r.id IN (SELECT id FROM @authorised_rooms)
Есть ли лучший способ сделать это?
EDIT:
Здесь - это скрипка с настройкой