ACL

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

Пару слов о реализации:
Таблицы в бд:
cms_modules - содержит id и uri модулей
users_groups - содержит id и имя групп
users - содержит данные пользователей, в данном случае нас будет интересовать только поле `group` которое содержит id группы
cms_access_list - служит для настройки доступа. Имеет поля `gid` - идентификатор группы и `mid` - идентификатор модуля.
Далее сразу после роутинга проверяем доступ, если доступ запрещен, то перенаправляем на страницу ошибки.
В итоге вырисовывается такая картина. У нас есть очень гибкая система контроля доступа, можно создавать почти неограниченное число групп (ограничивается разве что размером поля id в Таблице содержащей список групп) удалять редактировать группы, доступ можно настраивать как мне угодно.
Вроде как бы все.
.
Кадило крутится, лавэха мутится
Как гибкость пострадает?
Сделай в скрипте проверку привилегий и все.
.
Simba, Ну для проверки нужен id группы а вот так понадобится удалить группу, и ид уже недействителен
как вариант можно поробовать передавать в функцию проверки доступа uri модуля тогда думаю уже гораздо лучше будет
.
Кадило крутится, лавэха мутится
Screamer (16.09.2012/16:56)
Simba, Ну для проверки нужен id группы а вот так понадобится удалить группу, и ид уже недействителен
как вариант можно поробовать передавать в функцию проверки доступа uri модуля тогда думаю
Суть привилегий и групп, в том что группы наделяются привилегиями, а скрипт проверяет не группу, а привилегию. По этому ты так как делаешь сейчас, убиваешь смысл самого разделения на группы и присвоение привилегий и.
.
Screamer
Simba, ну и? вот например нужно показать ссылку на админку. Админка доступна только пользователям группы root. значит нужно проверить является ли пользователь членом группы root. и именно для этого нам нужен id Группы.
Подругому можно попробовать имя модуля,
с именем модуля уже возможности по шире.
По нему получаем список групп имеющих доступ и уже потом проверяем относится ли пользователь хотя бы к одной группе имеющей доступ к модулю.
.
У тебя не ACL, а RBACL, ибо есть роли.
В таком случае проверка должна выглядить как-то так:
if (RBACL::deny($role_id, 'adminpanel.show')) {
    echo '<a href="/adminpanel/index">Одминкэ</a>';
}
.
(\/)____o_O____(\/)
Screamer, кинь структуру таблиц, есть идея
.
Koenig,
`cms_modules`
  `id` int(11) unsigned NOT NULL auto_increment,
  `module` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
-------------------
`cms_access_list`
  `gid` int(11) unsigned NOT NULL, -- Идентификатор группы
  `mid` int(11) unsigned NOT NULL, -- Идентификатор модуля
  PRIMARY KEY (`gid`, `mid`)
-------------------
`users_groups` 
  `id` int(11) unsigned NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
-------------------
`users`
  `id` int(11) unsigned NOT NULL auto_increment,
  -- кучка полей --
  `group` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
-------------------

У мну есть функция для вывода ссылок
string Functions::anchor(string $uri, string $title, string $attributes)

Есть мысля добавить флаг $protected и в зависимости от его значения проверять привилегии, если доступа нет, то возвращать пустую строку.
Както так я себе это представляю
function anchor($uri = '', $title, $attributes = '', $protected = FALSE) {
  $link = '<a href="' . HOMEURL . '/' . $uri . '">' . htmlspecialchars($title) . '</a>';
  if ($protected === TRUE) {
    $module = System::$db->query("SELECT `id` FROM `cms_modules` WHERE `module` = '" . System::$db->real_escape_string($uri) . "'");
    if ($module) {
       $module = $module->fetch_assoc();
       $access = System::$db->query(
          "SELECT COUNT(*) FROM `cms_access_list` " . 
          "WHERE `gid` = '" . System::$user->group . 
          "', `mid` = '" . $module['id'] . "'"
       );
       if (!System::$db->result($access)) {
           return '';
       }
    }
  }
  return $link;
}
.
Koenig
(\/)____o_O____(\/)
Screamer, мой вариант
если я правильно понял
<?php
//   test access

$db_host = 'localhost';
$db_user = 'root';
$db_pass = '';
$db_name = 'qwerty';
$db_charset = 'utf-8';

$mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name); 
if ($mysqli->connect_errno) { 
die('Connect Error: ' . $mysqli->connect_errno); 
} else { 
$mysqli->set_charset('utf8'); 
}

/*
-- phpMyAdmin SQL Dump
-- version 3.2.3
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Sep 17, 2012 at 05:36 PM
-- Server version: 5.1.40
-- PHP Version: 5.3.3

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

--
-- Database: `qwerty`
--

-- --------------------------------------------------------

--
-- Table structure for table `cms_access_list`
--

CREATE TABLE IF NOT EXISTS `cms_access_list` (
  `gid` int(11) unsigned NOT NULL,
  `mid` int(11) unsigned NOT NULL,
  PRIMARY KEY (`gid`,`mid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Dumping data for table `cms_access_list`
--

INSERT INTO `cms_access_list` (`gid`, `mid`) VALUES
(4, 4),
(4, 5),
(5, 1),
(5, 2),
(5, 3);

-- --------------------------------------------------------

--
-- Table structure for table `cms_modules`
--

CREATE TABLE IF NOT EXISTS `cms_modules` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `module` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;

--
-- Dumping data for table `cms_modules`
--

INSERT INTO `cms_modules` (`id`, `module`) VALUES
(1, 'test1'),
(2, 'test2'),
(3, 'test3'),
(4, 'test4'),
(5, 'test5');

-- --------------------------------------------------------

--
-- Table structure for table `users`
--

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `group` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

--
-- Dumping data for table `users`
--

INSERT INTO `users` (`id`, `group`) VALUES
(1, 5),
(2, 4);

-- --------------------------------------------------------

--
-- Table structure for table `users_groups`
--

CREATE TABLE IF NOT EXISTS `users_groups` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;

--
-- Dumping data for table `users_groups`
--

INSERT INTO `users_groups` (`id`, `name`) VALUES
(1, 'test1'),
(2, 'test2'),
(3, 'test3'),
(4, 'test4'),
(5, 'test5');

*/


$sql = "SELECT * FROM `users` JOIN `users_groups` JOIN `cms_access_list` JOIN `cms_modules` ON users.id =1 AND users.group = users_groups.id AND users_groups.id = cms_access_list.gid AND cms_access_list.mid = cms_modules.id";

$res = $mysqli->query($sql);
while($row = $res->fetch_assoc()) {
print_r($row);
echo '<hr/>';
}
?>
.
(\/)____o_O____(\/)
смысл такой
$sql = "SELECT * FROM `users` JOIN `users_groups` JOIN `cms_access_list` JOIN `cms_modules` ON users.id ='" . $user_id . "' AND users.group = users_groups.id AND users_groups.id = cms_access_list.gid AND cms_access_list.mid = cms_modules.id";
Всего: 57