Задавайте вопросы, мы ответим
Вы не зашли.
Для начала опишу задачу:
Необходимо написать хелпер для squid, который мог бы определять уровень доступа для пользователя, в зависимости от данных в БД. Сам хелпер пишу на С, но в процессе написания, столкнулся с проблемой написания запроса к БД. Хочу ограничится одним запросом для всех случаев.
В хелпер попадает два значения - имя пользователя и запрашиваемый сайт. Есть 3 таблицы данных:
Users
-ID (поле ид)
-Name (имена пользователей)
-Access (уровни доступа(1,2,3) для пользователей)
DstDomain
-ID (поле ид)
-site (сайты)
-rlevel (уровни доступа(1,2,3) для сайтов)
Main - таблица соответствия уровня доступа к запрашиваемому сайту
Usr Dst level
No user rlevel 1 Base
Access 1 rlevel 2 Limited
Access 2 rlevel 3 Normal
Access 3 ALL Full
Уровень Limited должен включал все сайты с уровнем Base; уровень Normal должен включать все сайты с уровнем Limited и Base. НО НЕ НАОБОРОТ
допустим в запрос попадает пользователь, которого нет в таблице Users, тогда проверяется запрашиваемый сайт в таблице DstDomain и если он с уровнем доступа rlevel 1, то пользователю присваивается уровень Base, если запрашиваемого сайта нет в таблице DstDomain или он с каким то другим уровнем доступа(rlevel2 или rlevel3) то ничего не возвращается.
Вторая ситуация.
В запрос попадает пользователь с уровнем доступа 1, тогда если запрашиваемый сайт с уровнем доступа 2 или 1 то пользователю назначается уровень Limited. Если уровня доступа у сайта нет или он равен 3, то ничего не возвращается. По аналогии все остальные уровни доступа.
И самое главное, что бы в любой момент можно было добавить в БД еще один уровень доступа для пользователей и сайтов, дописать таблицу соответствия и хелпер смог бы назначать новые уровни доступа без изменения в теле программы.
Пы.Сы. Подскажите подойдет ли такая структура БД и натолкните на идею написания запроса (знаю MySQL на базовом уровне).
Пы.Пы.Сы. Структура БД можно изменять, главное что бы исполняло основную функцию - на основании имени и запрашиваемого сайта, определяло уровень доступа.
Вообщем буду рад любым идеям и советам!
Неактивен
Таблицу соответствия лучше сделать избыточной
Usr Dst level
No user rlevel 1 Base
Access 1 rlevel 1 Limited
Access 1 rlevel 2 Limited
Access 2 rlevel 1 Normal
Access 2 rlevel 2 Normal
Access 2 rlevel 3 Normal
...
И решать задачу в три простых запроса:
1) по имени пользователя определяем access
2) по имени сайта -- rlevel
3) select level from main where Usr = '..' and Dst = '..'
Если хотите одним запросом, то это будет медленно работающий монстр типа
SELECT level FROM Main JOIN
(SELECT `Access`, 1 o FROM `Users` WHERE Name = 'Имя пользователя'
UNION
SELECT 'No user', 2 o ORDER BY o LIMIT 1) t1 ON Usr=`Access`
JOIN
(SELECT rlevel FROM DstDomain WHERE site ='сайт') t2 ON Dst = rlevel;
Неактивен
Идея на счет избыточной таблицы просто замечательная! Уже ломал голову как строить программу, что бы был "вложенный" доступ.
По поводу 3-х запросов. Мне кажется (могу ошибаться) что один большой запрос к БД, отработает быстрее чем 3 запроса в хелпере. Хотя нужно проверять.
Сам запрос строил похожего типа, но столкнулся с проблемой, когда запрашиваемого пользователя нет в таблице Users и для него должна пройти проверка на запрашиваемые сайты с доступом rlevel1 (Base).
Получалось так, что приходит имя пользователя, которого нет в таблице Users, в результате запрос всегда ничего не возвращал!
И можно короткое пояснение к "1 o", "2 o", "t1"... Что это и для чего? С БД редко работаю, не совсем понял назначение, можно ткнуть на ман!
Неактивен
"1 o" то же что и "1 as o". Вторая колонка по имени o в которую вносятся фиксированные значения 1 и 2, а затем за счет (ORDER BY o LIMIT 1) выбирается только одно в порядке возрастания. Это и нужно как раз для случая когда нет запрашиваемого пользователя. Но лучше так не извращаться, а сделать отдельный запрос и если нет результата, то в программе присвоить доступу значение "no user".
"t1" это синоним для таблицы, которая формируется подзапросом (SELECT `Access`, 1 o FROM `Users` WHERE Name = 'Имя пользователя'
UNION
SELECT 'No user', 2 o ORDER BY o LIMIT 1). Как и в предыдущем случае здесь пропущено ключевое слово AS, которое является необязательным.
Дело в том, что каждая таблица в части FROM должна иметь имя и если таблица формируется за счет подзапроса, то нужно ей присвоить какое-нибудь имя, например: t1,t2, ...
Неактивен
Огромное человеческое спасибо за идею и пример реализации запроса!
Неактивен