Телефонный справочник для Active Directory

Для тех, кто статью читать не захочет, сразу репозиторий на github.
А остальных под катом ждёт бессвязная и бессмысленная история о том, как я
Всю свою
И понеслось… Я стал интегрировать всё, до чего дотянусь, с AD. Аутентификация прокси, база сотрудников для СКД, Антивирус и т.п. И не хватало мне для счастья телефонного справочника, который бы брал все данные из базы AD. Уже полгода я то и дело мучаю гугл на эту тему, но результаты не утешительные.
Основные требования к такому справочнику:
- отдельное portable приложение. Каждый раз натыкаясь на web-based справочник думал «если уж поднимать для этого сервак — то там уже сделаю полноценный корпоративный портал, а сейчас мне нужен всего лишь маленький справочник.
- бесплатный
- Максимально простой и удобный в использовании. Он всегда представлялся мне просто таблицей с сортировкой и поиском
Из всего зоопарка подобного софта, что я обнаружил, можно выделить несколько типов:
- Громоздкие: Всякие корпоративные порталы jomportal, onlyoffice...
- Платные: В принципе то, что нужно от dovestones, от ithicos...
- Имеющие фатальный недостаток: от gourami(стрёмный, не запустился, ещё и фремиум), от dmtsoft(один из лучших, о его недостатках чуть ниже.), или тысяча всевозможных VB скриптов генерирующих HTML файл.
По поводу справочника от dmsoft
Выглядит он вот так

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

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

Возможность написания десктопного приложения на знакомом языке — что может быть лучше? Радости моей не было предела.
Но вот незадача… Дома маленький ребёнок, постоянно требующий внимания, а на работе внезапно работа. Кодить категорически некогда и негде.
Но судьба была ко мне благосклонна — днём воскресенья ребёнок решил поспать. Жена, видимо вспомнив мои восторженные вопли о том, как крут node-webkit, и разгадав мои тайные желания, в ответ на вопрос „чем займёмся, пока дитё спит?“

ответила „ну ладно… иди уже программируй“
Эпизод 1: Марш-бросок до прототипа
И так. У меня есть 1.5 — 2 часа на то что бы освоить новую технологию (даже две, так как nodejs я тоже, по сути, не знал) и написать с её помощью софт, который почему-то никто из опенсорс программистов до сих пор не написал.
Первым делом — спросил гугл насчёт связи nodejs с ActiveDirectory. Он подсказал целых два модуля: node-activedirectory и ldapjs. Разбираться, что к чему времени не было, так что выбор пал на первый.
КОД
Кстати насчёт
var ActiveDirectory = require('activedirectory'); var ad = new ActiveDirectory('ldap://example.com', 'dc=example,dc=com', 'superadmin', 'pass'); var groupName = 'Employees'; ad.getUsersForGroup(groupName, function(err, users) { if (err) { console.log('ERROR: ' +JSON.stringify(err)); return; } if (! users) console.log('Group: ' + groupName + ' not found.'); else { console.log(users); } });
Кстати насчёт
EMPLOYEES — группа в которую входят все текущие сотрудникиvar groupName = 'Employees';
РЕЗУЛЬТАТ
мда....ERROR: {"dn":"","code":49,"name":"InvalidCredentialsError","message":"80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db0\u0000"}
Попытка потыкать второй модуль привела к тому же результату, но за большее время. Курение манов, пинание знакомого nodejs-ника и шальная удача таки дали результат: суперадмин домена почему-то не аутентифицируется, а вот бесправный юзверь, созданный ради гостевого интернета, — сработал!
УРА
Времени на разбирательства с правами нету — поехали дальше.
- git init
- Лицензия
- грязный хак для дебаггинга
require('nw.gui').Window.get().showDevTools(); - копипаст старого кода
ВУАЛЯ
Можно начинать творить магию… Но уже прошёл почти час. Ребёнок может проснуться в любую минуту. Нет времени на магию — берём всё готовое.
Быстрый гуглинг выдал на-гора отличный скрипт для работы с таблицей TinyTable. Копипащу его целиком с примером к себе.
Чуть чуть кода
var ad = new ActiveDirectory(credentials.dn, credentials.dc, credentials.user, credentials.pass, {attributes: {user: [ 'cn', 'telephonenumber', 'mail' ]}}); // поменял эту строчку что бы доставало только ФИО телефон и мыло function users2table (users) { tablehtml = ''; for (i in users) { var user = users[i]; console.log(user); tablehtml+='<tr>'; tablehtml+= '<td>'+user.cn+'</td>' tablehtml+= '<td>'+user.telephoneNumber+'</td>' tablehtml+= '<td>'+user.mail+'</td>' tablehtml+='</tr>' } console.log(tablehtml); $('#table tbody').html(tablehtml); sorter.init(); }
ТАДАМИз кроватки раздался радостный плачь.
Эпизод 2: Утренний кофе
На часах 6:50 у меня примерно 20 минут…
- Убираем адресную строку и называем окошкоpackage.json
"window": { "title": "Telephone Directory", "toolbar": false } - Автофокус на поле поискаusers2table
$('#query').focus(); - добавляем отдел в таблицу, а точнее — забираем не что попало, а только ФИО, телефон, емэйл, отделСкрытый текст
var ad = new ActiveDirectory(credentials.dn, credentials.dc, credentials.user, credentials.pass, {attributes: {user: [ 'cn', 'telephonenumber', 'mail', 'department']}});tablehtml+= '<td>'+user.department+'</td>' - И раскрываем окно на весь экран, чтобы не париться по поводу размеровСкрытый текст
require('nw.gui').Window.get().maximize();
Уже весьма неплохоНо уже 7:30 и мне пора бежать.
Эпизод 3: Наводим марaфет
Во время обеда я снова вернулся к коду.
Первым делом добавил фичу, которую обдумывал всю дорогу на работу — кеширование. Ибо каждый раз ждать загрузки (пусть и всего несколько секунд) глядя на пустое окно — раздражает.
КОД
в событие получения ответа от ldap поменял это:
а так же добавил в пустое место в скрипте подгрузку с localstorage если не пустой
на это:users2table(users);
var localusers = localStorage.users; var ldapusers = JSON.stringify(users); if (localusers != ldapusers) {localStorage.users = JSON.stringify(users)} else {console.log('users didn\'t changed')}; users2table(JSON.parse(localStorage.users));
а так же добавил в пустое место в скрипте подгрузку с localstorage если не пустой
if (localStorage.users) users2table(JSON.parse(localStorage.users));
Пофиксил пару багов, причесал, добавил mailto ссылки для емейлов… В принципе всё.
ГОТОВО!Как раз и обед закончился.
Но данный функционал уже полностью покрывает все мои планы, так что на этом я пока и остановился.
Установка
- поставьте node-webkit
- скачайте релиз
- поместите файл private.js содержание
module.exports = { dn:"ldap://example.com" ,dc:"dc=example,dc=com" ,user:"user" ,pass:"pass" }; - запускайте
path\to\nodewebkit\nw.exe path\to\telephone-directory
Распространение
- Запакуйте каталог telephone-directory в .zip
- Переименуйте архив в .nw
- Немного магии
copy /b path\to\nodewebkit\nw.exe+path\to\telephone-directory telephone-directory.exe - докиньте все остальные файлы из node-webkit кроме nw.exe в каталог с telephone-directory.exe
Должно получиться так:

Всё — можно выкладывать на сетевой диск или распространять так, как вам вздумается





