Можно я ещё покритикую?
Лучше сделать ваши экшны user_edit, user_delete и т.п. не строчками, а дефайнами.
Это позволит уже на этапе компиляции видеть ошибки синтаксиса. И позволит избежать долгой отладки для ошибок набора вроде user_edlt и т.п.
А чтобы еще красивее было, можно методами через __call — $user->checkUserEdit(), $user->chickUserDelete(). Правда, чуть медленее будет работать, думаю, чем просто передача строк
Вот в этой статье есть очень интересный взгляд на систему прав, там, в частности, ваш подход критикуется: php.russofile.ru/ru/translate/rights/phpgacl/
Когда вам оно станет нужно — вы замучаетесь переделывать. Я придерживаюсь мнения, что лучше сразу думать о будущем. Что до конкретно гакла — да — он немного сложен, но всегда можно написать самому по проще, но подход в гакле более интересный.
Иерархичные группы для человека, бесспорно, самое удобное представление. Когда система/сервис развивается, рано или поздно придется к ней прийти. Тут я вас поддерживаю. Но требуются значительные накладные расходы. Становится весьма трудоемко (для процессора) определить права пользователя на объект: надо проверить соответствующие группы, исправить конфликты (определить какие права были выданы позже), проверить исключения.
Я как раз сейчас (не не прямо сейчас, а в ближайшие дни) думаю перейти к такой иерархичной системе. Назрело. Но я рад что не стал применять ее с самого начала, иначе бы просто закопался. А так система работает и у меня есть время сделать рефакторинг.
Подход чем-то похож на <a href=«en.wikipedia.org/wiki/Radix_tree»"">RADIX_TREE
Может автор статьи попробует написать класс для высоконагурженых систем, в которых битовые матрицы не совсем применимы (например системы с >1 миллиона юзеров)
А по вашему phpGacl не класс? :-) Он очень быстро работает и я думаю что с высокими нагрузками справится — там довольно быстрые выборки ну и + кэширование
В общем сериализация, по моему мнению, не самое лучшее решение.Да, это будет работать быстро, но в плане поддержки это будет не очень удобно. Когда вам надо будет что-то поменять, или например, сделать выборку из базы всех людей, с определенными права только для одного объекта, придется чуток парится. Если вам надо будет это выводить на странице — это будет очень тяжелым запросом.
Релизация с битами требует конкретного определения разрешено/запрещено, что исключает возможность наследования прав при древовидной структуре групп юзеров, как у Zend_Acl.
Метод мне не нравится по двум причинам:
1. Невозможность использования пользователя в нескольки групах. Покольку имхо, у политик прав должно быть 3 значения; разрешено, не разрешено, и установлено. Ну и приоритет запрета больше чем разрешения, например нам нужно сделать пользователя админом. Тоесть по умолчанию он есть в групе пользователи, где доступ к админке не определен (а по приоритету получается запрещен), просто добавляем пользователя в групу администраторы где доступ к админке явно разрешен, тоесть установлен, это имеет больший приоритет чем не установленое значение. Ну вобщем раздача прав пользователя сводится добавления его в групы и выкидыванием его из них. Если например есть три части сайта к которым нужны права доступа, то создается 3 групы в каждой разрешено только доступ к одной части, и можем легко давать пользователю доступ в любые части, простым присоидинением его в групу ту или другую или несколько. А если например есть та часть сайта при доступе к которой мы обязательно хотим запретить доступ к другим, то устанавливанием правила запрещено на групу, при любых других групах доступ он не получит. Тоесть получается такое унаследование. Что в вашем методе сделать нельзя. Тоесть у вас фактически нужно задавать права разрешения и запрета. А не просто разрешить то что можно. Все остальное и так запрещено по дефолту.
2. Расширение, например если добавился еще один метод. Тоесть к каждому полю с правами нужно добавлять еще по биту, а если после чего-то отказались в процесе модернизации сайта, то бит уже не удалишь так просто из середины. Он останется, в результате у вас будет куча ненужного мусора в базе.
1. Просто тут система будет работать по другому. Если вы хотите локализовать доступ, то устанавливайте в этом локальном участке новую группу. Ну а администратор — просто обязан видеть всё вне зависимости от запретов и групп в которых он состоит.
2. Вы не дочитали статью до конца. Во втором случае расписывается, как отказаться от битов.
Второй способ нарушает точно. И ничего страшного в этом нет. Нормализация — это хорошо, но необходимо в первую очередь думать, как и где оно будет использоваться :).
Я лично сначала строю нормализованные таблицы, а затем уже от общего перехожу к частному — денормализую таблицы и произвожу рефакторинг объектов. Это часть оптимизации.
тогда при дальнейшей работе возникнут проблемы, например при выборке всех админов, или выборке всех элементов на кот. пользователь имеет права, в общем при любой выборке будут проблемы. А заказчик рано или поздно захочет написать какой то фильтр/сортировку на права. Идея интересная, но применять её чревато проблемами при дальнейшей поддержке.
Эти проблеммы решаются, например дополнительной таблицей прав, к которой доступ идёт только в случае, когда необходим фильтр пользователей по правам.
Скорость основного приложения не замедлит (выборки новостей), единственное что необходимо будет следить за правами в объекте и таблицей прав отдельно при внесении изменений.
То есть будет существовать для каждого объекта (в нашем случае пользователя) «прокешированные» (в serialize виде) права и нормализованные права в отдельной БД.
Вообще, в данной статье, я не могу разбирать каждый нюанс — вы это сами понимаете. И время у меня не резиновое — писать столько кода. И статья разрастётся очень сильно. Причём метод решение проблемы с поиском и фильтрацией прав я рассмотрел в первой статье.
Эти две статьи просто обучающие, в которых я рассматриваю несколько подходов к решению данной проблемы. Я здесь не рассматриваю «самый универсальный» подход, который быстрее всех и решает сразу все проблемы работы с правами. Если-бы такой существовал, я уверен, мы бы уже знали о нём и пользовались везде.
У любого подхода есть свои плюсы и минусы — использование зависит от поставленных задач.
Ивините, но, чтобы не наступали другие на такие большие грабли скажу так:
Как говорят студенты кубинцы — это пиздьеза.
Не заморачивайтесь на битовых самках.
Доступ групп и юзеров к обьектам, и к модулям можно сделать гораздо легче. Причем без битовых масок.
Я тоже вначале пошел вашим путем. Буквально 2 месяца назад — понял как я заблуждался. Все можно было сделать проще и «юзабилити» с точки зрения как разработчика так и пользователя.
Теперь переделываю.
Можете пояснить зачем нужно наличие двух полей Allow и Disallow?
Почему не сделать на одном поле Allow и соответственно всё, что не разрешено (стоит там в 0) пользователю запретить?
Возможно будет наследование прав доступа от родительского обьекта, но если честно статью не читал просто глазами пробежал! Понравиласькартинка в заголовке!
Мммм, не видимо мне сложно отойти от своих стереотипов =(
Как только думаю о битовых масках доступа, сразу вспоминаю # chmod, и никак не могу увязать это с двумя полями… пошёл ещё раз перечитывать…
Если уж говорить о том, как оптимизируют работу сайта с большой посещаемостью, то промежуточные и конечные результаты сложных расчетов (в вашем случае — конечный результат выборки прав доступа) хранят в memcached, а не в базе. Снижение нагрузки на сервер от наплыва пользователей заключается в том, чтобы как можно меньше общаться с СУБД.
Все не плохо но ресурс растет, вы уперлись в производительность сервера, нужно добавлять машины, у вас 2 выхода простой репликация и горизонтальное портирование как натянуть вашу модель...?
Оптимизации системы разделения прав доступа в веб-приложении