Форум → Программирование → PHP для идиотов → Управление правами в социальной сети
Управление правами в социальной сети
Страницы: ← Предыдущая страница • Следующая страница →
-
12 января 2010 г. 2:47, спустя 24 секунды
artoodetoo, модель очень хороша… но вот мен интересует вопрос о производительности… касаемо запросов, ведь это необходимо делать будет несколько раз на одну страницу на одного пользователя… Хотя если продумать модель данных, такую что бы могла брать как из серриализованого массива(кеш, или же какой другой…), из базы (напрямую) и добавить на обновление кеша некие "триггеры" при добавлении/изменении ролей…Спустя 213 сек.В общем есть у меня другое представление системы управление прав, попробую завтра-послезавтра описать её… По ходу кардинально отличающийся от твоей, но не чего не могу сказать о производительности :) -
12 января 2010 г. 2:54, спустя 6 минут 41 секунду
Давай сосредоточимся на выполнении задачи. Вопрос кеширования — отдельная песня.
"Solve the business case, before optimizing the solution"
"One of the most common mistakes done even by experienced developers is starting to optimize code without identifying the problem"
© Ilia Alshanetsky (один из разработчиков PHP)ιιlllιlllι унц-унц -
12 января 2010 г. 3:10, спустя 16 минут 20 секунд
Поехали гонять запросы.
Listing 1. Вывод явно назначенных ролей в читабельном виде. Чисто для контроля.
WHERE (u.is_team=0) AND (c.is_team=1) означает "отношения пользователей к группам"
SELECT u.short_name AS user_name, c.short_name AS cont_name, l.short_name AS role_name
FROM x_relations AS e
INNER JOIN x_contexts AS u ON u.cont_id=e.user_id
INNER JOIN x_contexts AS c ON c.cont_id=e.cont_id
INNER JOIN x_roles AS l ON l.role_id=e.role_id
WHERE (u.is_team=0) AND (c.is_team=1)
результат:
user_name cont_name role_name
durov bobrdobr admins
mary bobrdobr members
ivanov bobrdobr members
john photo-moto admins
ivanov photo-moto members
petrov photo-moto members
Listing 2. У нас должна быть роль по-умолчанию. Это visitors (id=1)
Переписываем запрос на LEFT JOIN и ifnull()
SELECT u.short_name AS user_name, c.short_name AS cont_name, l.short_name AS role_name
FROM x_contexts AS u, x_contexts AS c
LEFT JOIN x_relations AS e ON (e.user_id = u.cont_id) AND (e.cont_id = c.cont_id)
INNER JOIN x_roles AS l ON l.role_id = ifnull( e.role_id, 1 )
WHERE (u.is_team = 0) AND (c.is_team=1)
результат с непрописанными явно отношениями
user_name cont_name role_name
guest bobrdobr visitors
durov bobrdobr admins
john bobrdobr visitors
mary bobrdobr members
ivanov bobrdobr members
petrov bobrdobr visitors
guest photo-moto visitors
durov photo-moto visitors
john photo-moto admins
mary photo-moto visitors
ivanov photo-moto members
petrov photo-moto membersιιlllιlllι унц-унц -
-
28 января 2010 г. 8:03, спустя 16 дней 2 часа 34 минуты
Listing 3. Какова роль пользователя john (id=3) в группе bobrdobr (id=5)
(см. требование 1)
SELECT ifnull(e.role_id, 1)
FROM x_contexts AS c
LEFT JOIN x_relations AS e ON (e.cont_id=c.cont_id) AND (e.user_id=3)
WHERE (c.cont_id=5)
Выведет "1" (т.е. группа visitors). Отношение не описано явно, сработало условие ifnull
Listing 4. Входит ли john в группу bobrdobr (как участник (2) или администратор (3))
(см. требование 1)
SELECT 1
FROM x_contexts AS c
JOIN x_relations AS e ON (e.cont_id=c.cont_id) AND (e.user_id=3)
WHERE (c.cont_id=5) AND (e.role_id IN(2,3))
вернет пустое множество, т.к. нет, не входит
если протестируем группу photo-moto …WHERE (c.cont_id=6)… то вернет "1"
Listing 5. Какие права есть у пользователя john (id=3) в группе bobrdobr (id=5)
(см. требование 2)
SELECT r.act_id
FROM x_contexts AS c
LEFT JOIN x_relations AS e ON (e.cont_id=c.cont_id) AND (e.user_id=3)
INNER JOIN x_rights AS r ON (r.cont_id=c.cont_id) AND (r.role_id=ifnull(e.role_id, 1))
WHERE (c.cont_id=5)
результат
act_id
1
3
5
(вывелись права для роли visitors)
Listing 6. Есть ли у john право на blog-post в группе bobrdobr?
(см. требование 2)
SELECT 1
FROM x_contexts AS c
LEFT JOIN x_relations AS e ON (e.cont_id=c.cont_id) AND (e.user_id=3)
INNER JOIN x_rights AS r ON (r.cont_id=c.cont_id) AND (r.role_id=ifnull(e.role_id, 1))
WHERE (c.cont_id=5) AND (r.act_id=2)
вернет пустое множество, т.к. нет у него права.
если протестируем группу photo-moto …WHERE (c.cont_id=6)… то вернет "1"
Listing 7a. В каких контекстах john выступает в роли admins?
(см.требование 3)
SELECT c.cont_id
FROM x_contexts AS c
INNER JOIN x_relations AS e ON (e.cont_id=c.cont_id) AND (e.user_id=3)
WHERE e.role_id = 3
выведет 6
Listing 7b. В каких контекстах john выступает в роли X, с учетом неявно назначаемой роли id=1 visitors?
(см.требование 3)
SELECT c.cont_id
FROM x_contexts AS c
LEFT JOIN x_relations AS e ON (e.cont_id=c.cont_id) AND (e.user_id=3)
WHERE ifnull(e.role_id, 1) = :X
Listing 8. В каких контекстах john может смотреть фотографии (act_id=3)
(см. требование 4)
SELECT c.cont_id
FROM x_contexts AS c
LEFT JOIN x_relations AS e ON (e.cont_id=c.cont_id) AND (e.user_id=3)
INNER JOIN x_rights AS r ON (r.cont_id=c.cont_id) AND (r.role_id=ifnull(e.role_id, 1))
WHERE r.act_id=3
права мы задавали только для групп, поэтому выведутся две записи "5" и "6"
для r.act_id=4 'photo-post' выведется только "6"
Вобщем основные требования выполяются для придуманной структуры. Все проверки можно выразить в SQL.
Фишка в управлении правами на основе назначаемых ролей + "роль по-умолчанию" + легко расширяемый набор прав на операции.ιιlllιlllι унц-унц -
12 января 2010 г. 11:18, спустя 3 часа 14 минут 29 секунд
artoodetoo, модель очень хороша… но вот мен интересует вопрос о производительности… касаемо запросов, ведь это необходимо делать будет несколько раз на одну страницу на одного пользователя…
Я бы завел такое кеширование: массив id всех контекстов, где роль данного пользователя отличается от роли по-умолчанию. Тогда обращаясь к любой странице можно быстро вычислить роль.
А если еще для каждого контекста кешировать полный набор допустимых в нем операций по ролям… тогда выяснится что мы засунули в кеш просто все данные о правах :)
Пока нет замеров на правдоподобно больших данных, рано чего-то оптимизировать, IMHO.
[tt]OOO!!! 1234[/tt]ιιlllιlllι унц-унц -
12 января 2010 г. 13:07, спустя 1 час 49 минут 33 секунды
Теперь о PHP.
Предположим мы фанаты MVC. Контроллер выглядит как класс с методами :) круто-крут-круто!
Наш роутер анализирует URL и извлекает из него "controller/action" типично для популярных фреймворков. Например вызывается
GroupController->index() или
PersonController->newPost()
Логично предположить, что в начале ЛЮБОГО ПУБЛИЧНОГО метода контроллера надо получить инфу о правах пользователя. Воспользуемся наследованием от общего предка и protected методом
class CustomController
{
protected
$userId,
$roleId,
$contextId,
$availableActions;
protected function applyContext()
{
$this->userId = Auth::currentUser();
$this->contextId = Router::$contextId;
$this->roleId = Context::getRole($this->contextId, $this->userId);
$this->availableActions = Context::getRights($this->contextId, $this->roleId);
if (!in_array(Router::$action, $this->availableActions))
throw new Exception('Access denied');
}
}
// …
class GroupController extends CustomController
{
public function index()
{
$this->applyContext();
// some code
// …
Template::render('group-index', $data);
}
public function newPost()
{
$this->applyContext();
// some code
// …
Template::render('new-post', $data);
}
// …
}
выше я приводил запросы, которые должны использоваться в Context::getRole($contextId, $userId) и Context::getRights($contextId, $roleId)
вот как-то так я это вижу…ιιlllιlllι унц-унц -
27 января 2010 г. 13:49, спустя 15 дней 41 минуту
Если у нас посты бывают разных типов "нейтраль/гневный/и т.д." и мы хотим через права ограничить добавление постов разных типов.
Как это встроить в Вашу модель? (я про class CustomController и его потомков)
Творить методы
GroupController->newPost_a
GroupController->newPost_b
не совсем красиво. -
27 января 2010 г. 15:04, спустя 1 час 15 минут 3 секунды
мне кажется тут необходимо реализовать некоторую связку "рейтинг"+пост, рейтинг в кавычках потому, что не совсем рейтинг.
Если у нас посты бывают разных типов "нейтраль/гневный/и т.д." и мы хотим через права ограничить добавление постов разных типов.
Как это встроить в Вашу модель? (я про class CustomController и его потомков)
Творить методы
GroupController->newPost_a
GroupController->newPost_b
не совсем красиво. -
27 января 2010 г. 15:19, спустя 15 минут 8 секунд
Творить методы
GroupController->newPost_a
GroupController->newPost_b
не совсем красиво.
некрасиво так называть методы, они должны говорить о сути действия. других некрасивостей не вижуιιlllιlllι унц-унц -
27 января 2010 г. 18:04, спустя 2 часа 44 минуты 56 секунд
Уточню.
Например у нас посты/тосты бывают трех типов: a,b,c.
По модели прав надо:
Вася может постить только типы А и С
Петя - только B
Света - А и В
Ваш код тут дает сбой … он либо дает постить либо нет - нет проработки "кому какого типа посты можно добавлять".
Вот и спрашиваю Вас: "как эти хотелки прав вставить в Ваш код"?
Как пример показал один из тупых вариантов - натворить кучу практически одинаковых методов. -
27 января 2010 г. 19:56, спустя 1 час 52 минуты 7 секунд
Вот не надо дезинформации! Только что сами писали — "придется завести по методу на создание каждого типа постов". Помоему это логично, пользователь в роли "крутой" может a, b и c, а в роли "так себе" только a.
В этой системе одно "право" дает ответ Да/Нет. Но почему бы не использовать 3 правила?
Но если хочется обойтись одним методом для трех разных случаев — делайте, пожалуйста. И в этом одном делайте дополнительные проверки для a, b и c на уровне скрипта. Дело вкуса. Только вы уже не сможете на уровне SQL одним запросом найти список ролей или пользователей, кто может выполнить конкретно "действие a". Помоему ТАК делать некрасиво.
Мой выбор — создавать по одному правилу для каждого действия. В роль можно включить сколько угодно правил.Спустя 216 сек.
По модели прав надо:
Вася может постить только типы А и С
Петя - только B
Света - А и В
Уточню не "Вася может". А "Роль крутые мальчиши" может.
А "Плохие мальчиши" может только "B".
То есть ваш т.н. "рейтинг" — это Роль.
Мы присваиваем роли конкретным пользователям. А права раздаем на уровне ролей. Это принципиальный момент!Спустя 223 сек.Еще раз:
$this->contextId = Router::$contextId; // мы определяем контекст для текущего URL
$this->roleId = Context::getRole($this->contextId, $this->userId); // Мы находим в какой роли выступает пользователь в данном контексте
$this->availableActions = Context::getRights($this->contextId, $this->roleId); // Мы получаем набор прав РОЛИ !!!
Набор прав роли в данном контексте может включать любое сочетание a, b, c и еще черт знает сколько действий.ιιlllιlllι унц-унц -
26 июня 2010 г. 23:23, спустя 150 дней 2 часа 26 минут
а делал ли ты наследование/включение прав (actions)?
читать новость
редактировать новость - включает в себя "читать новость" -
27 июня 2010 г. 6:34, спустя 7 часов 11 минут 42 секунды
Здесь — нет. Самоцитата: "для нашей условной социалки можно описать правила попроще, но так, чтобы одним SELECT получить ответ на любой вопрос"
А вот в теме Эксперименты с RBAC я разрешаю "задачи могут иметь подзадачи".ιιlllιlllι унц-унц -
27 июня 2010 г. 6:28, спустя 23 часа 53 минуты 39 секунд
эта поебень называется матричный доступ
http://ru.wikipedia.org/wiki/Избирательное_управление_доступом
как в линуксе - rwx отдельно для групп, отдельно для пользователей
либо делать отдельную таблицу, как artoodetoo, либо в таблицу запией добавлять два поля: права для групп, права для пользователей (можно сериализованным массивом в текстовое поле).читать новость
редактировать новость - включает в себя "читать новость"
в линухе не включает напримерне всё полезно, что в swap полезло
Страницы: ← Предыдущая страница • Следующая страница →
Пожалуйста, авторизуйтесь, чтобы написать комментарий!