[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Логика
apc
Всем привет. У меня такой вопрос:
мне нужно разделение полномочий пользователей...
будет таблица в БД в которой будут описанны полномочия.
И вот тут нужна логика, мне в поле в таблице юзеров создать графу
в которой будут перечислины права (пример 01000001001010), но этот
вариант плохой((( (если вы не знаете чем он плох - НЕ спрашивайте)).
Есть еще вариан можно каждой привилегии присвоить значение 1 2 4 8 16 32 64 128 и тд (мысль уловили..)
Так вот может кто подскажет как луше....



Спустя 51 минута, 4 секунды (13.01.2009 - 15:19) sergeiss написал(а):
Лучше, мне кажется, сделать для каждого типа полномочия отдельное логическое поле. Это позволит, во-первых, сделать всё очень наглядно, а во-вторых, можно будет спокойно добавлять/удалять типы полномочий, при этом не затрагивая другие типы полномочий. Также, на программном уровне будет очень легко (и наглядно!!!) сделать управление всеми этими полномочиями.

Я сам как раз нечто подобное делаю сейчас. Так что тема ну очень близкая и "родная" smile.gif

Спустя 11 минут, 58 секунд (13.01.2009 - 15:31) apc написал(а):
Цитата (sergeiss @ 13.01.2009 - 12:19)
Лучше, мне кажется, сделать для каждого типа полномочия отдельное логическое поле. Это позволит, во-первых, сделать всё очень наглядно, а во-вторых, можно будет спокойно добавлять/удалять типы полномочий, при этом не затрагивая другие типы полномочий. Также, на программном уровне будет очень легко (и наглядно!!!) сделать управление всеми этими полномочиями.

Я сам как раз нечто подобное делаю сейчас. Так что тема ну очень близкая и "родная" smile.gif

для полномочий есть отдельная таблица.....
но я хочу что бы сумма полномочий помещалась в поле в таб с юзерами
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
это поможет собрать (сумма) полномочия
но как мне разложить все назад????????
2+8+32 = 42
но как 42 разложить назад

Спустя 16 минут, 25 секунд (13.01.2009 - 15:48) sergeiss написал(а):
Я говорю не про список полномочий, а про то, что у каждого пользователя лучше сделать отдельные поля с полномочиями, в таблице с юзерами.
Типа такой чтобы таблица была:
user_id integer
user_name char(200)
en_save boolean
en_read boolean
en_resend boolean
en_forum boolean
ну и так далее.

Плюсы моего подхода я уже описывал: я могу легко и просто управлять каждой фичей. Запросы на выборку прав, на их ввод и изменения делаются легко, просто и очень наглядно. Вплоть до того, что прямо при просмотре таблицы уже будешь сразу видеть, кто на что имеет права.

Минусы твоего подхода мне видятся такие. Во-первых, очень всё "засекречено". Причем, проблемы в первую очередь себе создаешь. В частности, "как разложить 42 назад" и другие.
Во-вторых, какого размера у тебя будет это самое поле, сколько бит? И что ты будешь делать, если понадобится больше полномочий, чем имеется бит? Или сразу заложишь много, с запасом?

Спустя 13 минут, 54 секунды (13.01.2009 - 16:02) apc написал(а):
Насчет бит тип bigint вместит столько ............=)))
А так твой вариант был моим планом Б)))
Только я вынес полномочия в другую таблицу.... так бедет логичнее да и зачем мне таскать с собой лишние переменные при запросе)))
спс

Спустя 6 минут, 18 секунд (13.01.2009 - 16:08) sergeiss написал(а):
У меня это - план "А" smile.gif

А насчет лишних переменных при запросе не понял. Зачем их таскать? Запрашивай только то, что надо в нужный момент времени.

Спустя 48 минут, 28 секунд (13.01.2009 - 16:56) apc написал(а):
Цитата (sergeiss @ 13.01.2009 - 13:08)
У меня это - план "А" smile.gif

А насчет лишних переменных при запросе не понял. Зачем их таскать? Запрашивай только то, что надо в нужный момент времени.

я просто селектом выбераю все данные и из за этого при запросе mysql будет извлекать переменные (полномочия) которые я буду использовать не очень часто. По этому я их и вынесу

Спустя 47 секунд (13.01.2009 - 16:57) apc написал(а):
какая не какая оптимизация =)

Спустя 5 минут, 38 секунд (13.01.2009 - 17:03) sergeiss написал(а):
Фигасе... Про оптимизацию он думает... А в Селекте - выбираешь все данные, в т.ч. и не нужные. Неувязочка получается.
А вот разнесение данных в разные поля и запрос только тех данных, которые нужны, это и есть оптимизация. Оптимизация как БД, так и твоего кода.

Спустя 11 минут, 57 секунд (13.01.2009 - 17:15) dfsq написал(а):
и все-таки правильнее использовать битовые маски
во-первых, не таблицы не засоряются левыми столбцами
во-вторых, удобнее хранить права пользователей в виде одного числа
в-третих, это не так сложно перходить от суммы (маски) составляющим. можно немного заморочится написать функцию которая будет все это делать.
к примеру 42 (dec) = 101010 (bin)
сразу видно, что у пользователя есть право на действие которое описывается значением 2 (2 в степени 1), 8 (2 в степени 3), 32 (2 в степени 5).
всего-то надо перевести число в двоичный вид, пробежаться по каждому значению с конца.

Спустя 12 минут, 56 секунд (13.01.2009 - 17:28) sergeiss написал(а):
Цитата (dfsq @ 13.01.2009 - 17:15)
сразу видно, что у пользователя есть право на действие которое описывается значением 2 (2 в степени 1), 8 (2 в степени 3), 32 (2 в степени 5).
...
всего-то надо перевести число в двоичный вид, пробежаться по каждому значению с конца.

А теперь представь, что тебе нужно сделать запрос, чтобы определить количество пользователей с определенными правами. В случае с моим вариантом пишется простой Селект.
Типа такого:
SELECT COUNT(*) FROM MY_TABLE WHERE EN_STAT_EDIT=TRUE.

А теперь покажи мне, плз, аналогичный запрос в использованием битовых масок blink.gif

Или попробуй написать запрос для обновления определенного права у данного юзера. Сможешь? smile.gif

И к тому же, любой человек, просматривая таблицу, должен уметь быстро перевести число в двоичный вид, и помнить, какой бит отвечает за какую фичу. Иногда это умению называют "профессионализмом", но того, кто заложил такой алгоритсм, ругают всякими нехорошими словами.

Спустя 9 минут, 54 секунды (13.01.2009 - 17:38) dfsq написал(а):
Не думаю, что ты будешь выставлять для каждого пользователя права отдельно. Для этого и существуют "группы пользователей". И по-моему архитектурно более правильно, делая выборку, смотреть имеет ли группа, к которой принадлежит пользователь, права для того или иного действия, а не писать в запросе что-то типа ... and can_edit=true and can_view=true

Спустя 2 часа, 19 минут, 4 секунды (13.01.2009 - 19:57) kirik написал(а):
Цитата (dfsq @ 13.01.2009 - 09:38)
Не думаю, что ты будешь выставлять для каждого пользователя права отдельно.

Соглашусь с этим.

Я реализовывал систему прав таким образом -
4 таблицы
users { user_id | username } - тут собственно юзеры
groups { group_id | group_name } - тут хранятся группы и их названия
groups2users { group_id | user_id } - тут хранятся пары группа/юзер. Так как один юзер может быть в нескольких группах, которые будут вызываться на разных страницах. Например у нас есть обычный юзер (группа regular_member) и модератор форума (группа forum_moderator). На всех страницах сайта он имеет права обычного пользователя, но как только заходит на форум - у него перезаписываются права на модераторские (посредством вызова новой группы прав, если конечно юзер в ней присутствует)
permissions { group_id | permission_name | value } - тут хранятся права для групп. По дефолту, когда добавляем право - у нас оно добавляется к группе regular_member. Если данное право отсутствует для другой группы, то значение берется как для regular_member.

Вобщем-то реализация наверное похожа на большинство уже готовых (в SMF примерно также), но она своя =)

Спустя 13 часов, 15 минут, 37 секунд (14.01.2009 - 09:12) sergeiss написал(а):
Цитата (dfsq @ 13.01.2009 - 17:38)
Не думаю, что ты будешь выставлять для каждого пользователя права отдельно. Для этого и существуют "группы пользователей". И по-моему архитектурно более правильно, делая выборку, смотреть имеет ли группа, к которой принадлежит пользователь, права для того или иного действия, а не писать в запросе что-то типа ... and can_edit=true and can_view=true

Это уже другой вопрос! Его реализация подобна той, что я писал. Т.е. все равно надо использовать не битовые матрицы, а отдельные переменные. Ну не получится с битовыми матрицами ничего разумного. Не верю smile.gif
А уж будут разрешения индивидуальные или групповые - это уже не столь принципиально.

Спустя 1 день, 10 часов, 32 минуты, 39 секунд (15.01.2009 - 19:45) Alchemist написал(а):
sergeiss, ты не прав ! (с)

Битовые маски не только могут, но и активно используются, в качестве разграничителей доступа во многих программах.

В чем основной недостаток отдельных переменных ? В их кол-ве. Проблем нет если их всего 2-3, а ну как 10-20 ? Замучаешься обрабатывать их самих и все их возможные сочетания. Между тем, при использовании битовых масок, я могу хранить 8(!) независимых переменных в одном поле(в одной переменной) типа TINYINT.

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

Еще чуть-чуть теории и плавно перейдем к практике. smile.gif
Многие молодые (и не очень) программиты склонны усложнять решения задач, часто не видя того что находится у них прямо перед глазами. (Я тоже иногда так делаю, и это одна из причин того что я нахожусь на этом форуме - часто сторонний взгляд помогает найти более простое решение.)
Логически рассуждая, наиболее правильным методом работы с битовыми масками должны быть битовые операторы !

Так, например, если мне нужно
Цитата (sergeiss @ 13.01.2009 - 16:28)
сделать запрос, чтобы определить количество пользователей с определенными правами.
то все что мне надо это сравнить права пользователя с искомой маской:
PHP
$que = "SELECT COUNT(*) FROM `MY_TABLE` WHERE `permission` & ".$permission_mask;

И вуаля ! Например если $permission_mask = 4;, то найдутся все пользователи у которых второй бит равен 1. И т.д...

Более того, если стоит задача посчитать пользователей у которых есть только определенные права, то тебе придется вписывать в запрос ВСЕ имеющиеся у тебя переменные, а мне всего лишь поменять оператор '&' на '=':
PHP
$que = "SELECT COUNT(*) FROM `MY_TABLE` WHERE `permission` = ".$permission_mask;

Но и это еще не все !

Если завтра у тебя добавится еще одна переменная, то тебе придется исправлять все подобные запросы везде где они есть (ведь у тебя должны перечисляться все переменные), а мой запрос не изменится вообще !

Вот таким образом, Лом...(с)

ЗЫ: Подумал и решил добавить, что я не агитирую за поголовный переход на битовые маски. При наличии всего 2-4 переменных, может получиться, что маски скорее затрудняют работу, нежели облегчают её, и даже при большем количестве, бывают случаи что удобнее пользоваться отдельными переменными.
Вобщем, все зависит от проекта и программиста smile.gif

Спустя 12 дней, 10 часов, 9 минут, 33 секунды (28.01.2009 - 05:55) Guest написал(а):
обратное разложение
2+8+32=42

42 - max(<42) = 42 - 32 = 10; rule[]=32;
10 - max(<10) = 10 - 8 = 2; rule[]=8;
if (2) rule[]=2;
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.