пятница, 26 июля 2013 г.

Вывод html таблицы с данными из БД с сортировкой без обёртки Drupal 7.

Возникла необходимость вывести данные в форму с сортировкой своего SQL-запроса без использования какой бы то ни было обёртки, предоставляемой Drupal 7, так как идей, как завернуть туда запрос так и не возникло, вполне возможно, потому что запрос кривой. Делал с помощью API mysqli.

Так или иначе, делается это очень просто:

Для начала, необходимо сделать массив $header будущей таблицы:
$header = array(
array('data' => 'Видимое имя поля', 'field' => 'field in db'),
);

Теперь надо получить настройки базы данных, используемой Drupal 7 по умолчанию, берутся они из суперглобальной переменной $databases:

global $databases;
$current_base = $databases['default']['default'];
$mysqli = new mysqli($current_base['host'],$current_base['username'],$current_base['password'],$current_base['database']);

Далее необходимо установить кодировку UTF-8 по-умолчанию:

$mysqli->set_charset("utf8");

А дальше выполняем непосредственно сам запрос, при этом предполагается, что в $query находится корректный SQL-запрос:

$result = $mysqli->query($query);

Далее, обходим все записи и строим массив строк:

while ($record = $result->fetch_object()) {
$rows[] = array(
             $record->title,
       );
}

А далее просто рендерим получившуюся таблицу и выводим

$output = theme('table', array('header' => $header, 'rows' => $rows));
return $output;

В результате этих нехитрых действий получаем таблицу, в которую выведен наш запрос и заголовок которой автоматически сгененрирован для передачи методом GET параметров сортировки таблицы. Теперь надо только обработать полученные данные, например, следующим образом:

Для удобства был создан костыль, содержащий запись "имя поля" - "имя поля в БД", так как в GET друпалом передаётся название поля в точности, как оно отображается для пользователя:

$map = array (
'Видимое имя поля' => 'field in bd',
);

А далее просто обрабатывал массив $_GET и добавлял к строке $query сортировку по полю, возрастающую или убывающую:

if (isset($_GET['sort'])) {
$query.=" ORDER BY ".$map[$_GET['order']]." ";
$_GET['sort'] == 'asc' ? $query.="ASC" : $query.="DESC";
}




четверг, 4 апреля 2013 г.

Интеграция Drupal 7 и LDAP (Active Directory) для самых маленьких

1. Постановка задачи

Нужно было мне сделать авторизацию на корпоративном сайте в локальной сети с помощью LDAP, однако я никогда не работал с ним, не знал что это такое и столкнулся с недостатком статей по этой теме именно применительно к друпалу и готовым модулям, однако, если смотреть внимательно на все настройки и понимать, что такое LDAP и как он отдаёт информацию, то всё просто и понятно.
Дано:
Приведу версии друпала и модуля на момент написания статьи, так как практически во всех примерах в сети используется старая версия модуля LDAP, настройки которой не соответствуют новой.

2. Этап анализа

Что же такое, этот LDAP (англ. Lightweight Directory Access Protocol — «облегчённый протокол доступа к каталогам», почитать в Wikipedia)? Это большая "адресная книга", представляющая собой дерево, где корень - весь мир, а каждая запись представляет либо пользователя, либо группу, либо машину (в AD точно, другие реализации LDAP я не видел). Сразу стоит сказать, что PHP получает записи LDAP в виде ассоциативного массива и в настройках модуля нам нужно будет указывать поля этого массива, из которого нужно брать данные.
Чтобы посмотреть, как записи хранятся в каталоге и что они из себя представляют можно использовать Apache Directory Studio. Процесс установки подробно описан на странице этой программы, а ещё ценно, что она может быть плагином к Эклипсу, что и будет рассмотрено в данной статье.
Как сказано на официальном сайте, необходимо добавить update site и с него поставить плагин. Идём в меню Help -> Install new software. В появившемся окне нажимает кнопку Add...
В диалоговом окне добавляем, собственно, адрес сайта. На момент написания статьи адрес был таким: http://directory.apache.org/studio/update/2.x 
Далее устанавливаем плагин Apache Directory Studio LDAP Browser (Эклипс сам покажет пакеты, доступные на update site, их не много).
После установки Apache Directory Studio, в Эклипсе переключим перспективу на LDAP. По умолчанию, в выпадающем меню перспектив её не будет, она доступна под пунктом Other.
Переключив перспективу, идём в меню File - New - LDAP Connection, и видим следующее диалоговое окно:
Connection name: имя соединения
Hostname: имя сервера LDAP или его IP-адрес или, что интересно, название домена, правильно настроенный DNS будет вам отдавать IP контроллера домена при попытке обратится непосредственно к домену. Это удобно, если у вас в локальной сети несколько контроллеров, тогда в случае отказа одного соединение всегда будет установлено. Например, у нас основной контроллер - one.donaim.com, а резервный - two.domain.com. Пишем в строке подключения domain.com и какой-то из контроллеров нам да ответит.
Port: по умолчанию тут будет не такой порт 389. Он используется при подключении с зашифрованным соединением, однако в моём случает возникли проблемы с сертификатом и, методом nmap, был найден порт 3268 на который ходят незашифрованные соединения. Естественно в продакшне нужно будет позаботиться о надёжном шифровании.
Жмём Next и видим:
На данном экране нужно ввести учётные данные записи, имеющей права на просмотр каталога. С точки зрения безопасности лучше создать ограниченную учётку и не давать изменять данные из сторонних программ. Для сетей Microsoft нужно указывать имя пользователя в формате, приведённом выше. 
Жмём Next и Finish.
Берём мыша и в левом нижнем углу тыкаем два раза левой кнопкой на созданном подключении. Если всё хорошо, будет установлено соединение с каталогом.
Что мы видим? Левый верхний столбец напоминает дерево, виденное в панели управления ролью доменной службы на сервере-контроллере домена. Зачем сюда лезть, если можно слазить на контроллер домена? Затем, что тут вы увидите имена полей именно так, как их будет получать PHP, что пригодится впоследствии при настройке подключения, а так же в принципе пригодится, дабы десять раз не лазить на контроллер что-то посмотреть.
Если в дереве мы выберем какой-либо объект и ткнём в него мышой пару раз, он откроется в фрейме по середине и мы сможем увидеть детальную информацию о нём. Какие поля нам впоследствии пригодятся?
  1. mail - обязательно должен быть заполнен при создании нового пользователя, так как без этого поля невозможно заполнить поле mail в друпал, а, значит, невозможно создать нового пользователя при авторизации с помощью LDAP.
  2. memberOf - в этих полях пишутся группы, к которым принадлежит пользователь.
  3. sAMAccountName - логин пользователя.
Разберём подробнее одну из записей, например memberOf: CN=IT Dep,OU=Groups,OU=itloc,DC=it,DC=loc
Здесь: CN - имя сущности (пользователя), OU - название подразделения, DC - две записи, образующие имя домена и указывающие на корень дерева LDAP.

3. Настройка модуля LDAP

Пропущу установку модуля, это и так всё понятно. В моём случае нужно было включить Authentification и Authorization, эти модули вы найдёте в списке модулей (называются они немного по другому).
Настройка сервера (LDAP Server Configuration):
Так как скриншот всей страницы огромен и на нём всё равно ничего не видно, опишу словами:

Connection Settings
  • Name: уникальное имя сервера в системе друпал
  • LDAP Server Type: выбираем Active Directory.
  • LDAP Server: пишем домен или сервер, как сказано выше
  • LDAP Port: у меня пока 3268, однако можно оставить порт по умолчанию, поставить галку на Use Start-TLS, но тогда в систему надо ставить корневой сертификат контроллера домена
Binding Method
  • Service Account Bind: так и оставляем
  • DN for non-anonymous search: имя пользователя, имеющего права на просмотр каталока
  • Password: пароль
LDAP User to Drupal user relationship
  • Base DNs for LDAP users, groups, and other entries: сюда нужно вписать корень дерева который узнали выше, например dc=domain,dc=com. 
  • AuthName attribute: sAMAccountName
  • Email Attribute: mail
LDAP Group Configuration
галочки поставьте как надо конкретно для вас, настройки в этой форме нужны для работы модуля Authorization, который позволит автоматически назначить роли пользователю при логине на сайт.
  • Name of Gtoup Object Class: group
  • Attribute in User Entry Containing Groups: memberOf 
Настройки пользователя (LDAP User Settings) я касаться не буду, там опять же галочки по вкусу.

Настройка аутентификации (LDAP Authentication Settings), так же галочки по вкусу.

Настройка авторизации (LDAP to drupal role Configuration)
В II. LDAP TO DRUPAL ROLE MAPPING AND FILTERING в поле Mapping of LDAP to drupal role (one per line) следует задать маппинг групп в LDAP на роли LDAP. Представление группы мы видели выше в поле memberOf, а маппинг будет выглядеть так:
CN=IT Dep,OU=Groups,OU=itloc,DC=it,DC=loc|admin
Здесь слева от разделителя "|" значение поля memberOf, а справа имя группы друпала.
С галкой Only grant drupal roles that match a filter above стоит согласиться, галки в следующей форме задают когда пользователю давать права. У меня они выставлены все.

Вот и всё, если всё прошло нормально, то вы сможете залогиниться на сервер под пользователем из AD и он будет автоматом внесён в таблицу People друпала и ему будут присвоены роли. Если что-то пошло не так и логин невозможен, то это 99% ошибка настройки сервера. Протестировать его можно на странице настройки серверов LDAP нажав на test в колонке Operations списка серверов. 
Вводим в поле Testing Drupal Username существующее в AD имя (например kuraev, тут имя домена добавлять не нужно) и, если запрос успешен, то вам будет показана таблица с данными о пользователе, похожая на виденную в эклипсе. Если таблицы нет, то идём и проверяем настройки, имя пользователя, порт и шифрование. На вкладке Settings настройки модуля LDAP в разделе Development ставим галку на Enabled Detailed LDAP Watchdog logging. Это даст в Reports - Recent Log Messages вывод функций модуля LDAP.