Хранение доступа пользователей к страницам в MYSQL

Приветствую всех, кто заинтересовался таким вопросом и попал сюда!

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

Идея была в следующем:

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

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

Однако практически первое Но, с которым я столкнулся это какие вообще есть способы хранения доступа пользователей в БД MYSQL? Как это реализовывалось под капотом? Ну так вот первое к чему я пришёл это хранение в таблице пользователей в текстовом поле записей типа "1,3,8,45,", что означало - какие ID модулей доступны конретному пользователю. Таким образом пользователь логинился, сайт на основе записей пользователя выдавал ссылки только на те страницы, которые были юзеру разрешены.

Теперь настал момент переписать приложение по-нормальному, и снова этот вопрос, какие еще варианты есть хранения в базе данных доступа к страницам, если "ну допустим" количество этих страниц "стремится в бесконечность", как и количество пользователей?

0
Автор поста оценил этот комментарий

Неужели никаких закономерностей нет? Ты когда добавляешь права пользователям ведь чем-то руководствуешься? Какими-то правилами?


Если совсем уникальные модули, то это не задача разграничение доступа, это что-то совсем другое, возможно с архитектурой всей системы что-то напутано.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Закономерности есть за исключением десятка юзеров. Закономерности такие: в зависимости от отделения работы, руководителя и должности пользователя ему назначаются модули, однако некоторые модули уникальные и нужны конкретному пользователю, другие конкретно только двум-трём, третьи исключительно мои, но иногда даются в просмотр другим на некоторое время (например, пока я в отпуске). Там вобщем такая круговерть с ними...

показать ответы
1
Автор поста оценил этот комментарий

Первое, что нужно сделать, это отделить модули от пользователей.


То есть добавить ГРУППЫ.


Это, практически, самое первое и основное, на чем строятся все системы разграничения доступа...

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Спасибо! У меня получится кол-во пользователей = кол-ву групп, там полный разнобой по доступу. Тоже думал сгруппировать, т.к. это бы облегчало процесс добавления нового модуля - не множеству пользователей, а одной группе, но блин так не выходит.

показать ответы
0
Автор поста оценил этот комментарий

что-то типа такого: https://sqlize.online/s/8H

но это просто набросок. если данных будет прям много, то нужно грамотно построить индексы, правильно задать ограничения на длины строковых полей и кучу всего ещё учесть

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Спасибо! Получается данные будут браться из двух таблиц с помощью джоинов, для меня ничего сложного, но вот инфы про производительность одного запроса на множество данных в одной таблице с помощью FIND_IN_SET против другого запроса на такое же множество с помощью JOIN не найти. Вариант смоделировать оба варианта на кастомной БД и написать тест на PHP на время выполнения каждого, оно и покажет. Сейчас у меня такой запрос: SELECT form_id, form_description FROM forms, users WHERE users.id = $session_id AND FIND_IN_SET(forms.form_id, users.access) ORDER BY form_id, где в поле access как раз записи вида "1,3,8,45,". При добавлении пользователя в интерфейсе я вывожу чекбоксы соответствующих модулей и отправляю отмеченные в БД в виде текста в поле acces.

0
Автор поста оценил этот комментарий

А от отбратного нельзя, когда у каждого модуля есть поле с авторизированными пользователями по id, которое и проверяется (тут видимо удобней кого больше: пользователей или модулей и динамика их изменения (при добалении пользователя будет сложно прописывать его в поле каждого модуля)).

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Спасибо! Вот об этом очевидном я и не подумал, надо будет посмотреть будут ли у такого варианта подводные камни. Как минимум да, нужно будет выполнять два запроса в БД на добавление данных пользователя в одну таблицу и на добавление данных доступа этого пользователя в другую.

0
Автор поста оценил этот комментарий

в mysql, вроде, появилось поле типа json. Лучше его использовать

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Ок, спасибо, тоже думал в эту сторону, пока изучаю про json в mysql

0
Автор поста оценил этот комментарий

стремится в бесконечность? ну тогда ты попал, здесь MySQL тебя не спасёт. нужно что-то типа ClickHouse или Tarantool. а если серьёзно, то зачем изобретать велосипед и не воспользоваться готовой CMS?

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Ну "стремится в бесконечность" это конечно условно, CMS не позволит мне сделать нужный мне интерфейс, модули. Ну например у меня есть модуль по просмотру изображений, заполнения, вывода и редактирования собственных визиток, учета платных услуг... вобщем каждый модуль это типа мини-программа.

показать ответы
0
Автор поста оценил этот комментарий

Гуглите основы проектирования БД, раздел "один ко многим" и будет вам щастье.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Спасибо, уже на хабре. Проектирование БД надо подтягивать действительно.

1
Автор поста оценил этот комментарий

хранишь строки вида user_id, module_id

для пользователя вытаскиваешь все строки, получаешь все модули, куда у него есть доступ

либо в конкретном модуле ищешь строку с модулем и пользователем, проверяешь, есть ли доступ

кстати, хранить у пользователя json-строку со списком модулей тоже норм

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Спасибо! Да именно так я и вывожу ссылки на модули с помощью такого запроса:

SELECT form_id, form_description FROM forms, users WHERE users.id = $session_id AND FIND_IN_SET(forms.form_id, users.access) ORDER BY form_id, где в поле access как раз записи вида "1,3,8,45,". Само поле имеет тип varchar(100). Однако я почему и спрашиваю не приведет ли запрос с FIND_IN_SET к деградации скорости выборки, если кол-во модулей достигнет большого количества. Опять же увеличивать поле varchar нужно будет постоянно, а хотелось бы, чтобы БД хранила именно столько бит инфы сколько туда попало. В общем было какое-то подозрение что что-то я делаю не так. А может я и заморачиваюсь.

показать ответы