Telephone Directory

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




    Для тех, кто статью читать не захочет, сразу репозиторий на github.

    А остальных под катом ждёт бессвязная и бессмысленная история о том, как я дошёл до жизни такой, при помощи node-webkit, написал приложение, которого джва года ждал.
    Всю свою сознательную жизнь карьеру сисадмина я восхищался Active Directory от MS. И как только появилась такая возможность — внедрил её на предприятии, где работаю.

    И понеслось… Я стал интегрировать всё, до чего дотянусь, с AD. Аутентификация прокси, база сотрудников для СКД, Антивирус и т.п. И не хватало мне для счастья телефонного справочника, который бы брал все данные из базы AD. Уже полгода я то и дело мучаю гугл на эту тему, но результаты не утешительные.

    Основные требования к такому справочнику:
    1. отдельное portable приложение. Каждый раз натыкаясь на web-based справочник думал «если уж поднимать для этого сервак — то там уже сделаю полноценный корпоративный портал, а сейчас мне нужен всего лишь маленький справочник.
    2. бесплатный
    3. Максимально простой и удобный в использовании. Он всегда представлялся мне просто таблицей с сортировкой и поиском


    Из всего зоопарка подобного софта, что я обнаружил, можно выделить несколько типов:
    • Громоздкие: Всякие корпоративные порталы jomportal, onlyoffice...
    • Платные: В принципе то, что нужно от dovestones, от ithicos...
    • Имеющие фатальный недостаток: от gourami(стрёмный, не запустился, ещё и фремиум), от dmtsoft(один из лучших, о его недостатках чуть ниже.), или тысяча всевозможных VB скриптов генерирующих HTML файл.
    Видел когда-то ещё и серверный вариант на php, правда не нашёл его при написании статьи. Его можно отнести к 3-ей группе, так как требование сервера для меня является недостатком.
    По поводу справочника от dmsoft
    Выглядит он вот так

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

    Ничего не предвещало беды решения этой проблемы, но позавчера я узнал о node-webkit!

    Возможность написания десктопного приложения на знакомом языке — что может быть лучше? Радости моей не было предела.
    Но вот незадача… Дома маленький ребёнок, постоянно требующий внимания, а на работе внезапно работа. Кодить категорически некогда и негде.
    Но судьба была ко мне благосклонна — днём воскресенья ребёнок решил поспать. Жена, видимо вспомнив мои восторженные вопли о том, как крут 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);
      }
    });
    

    Кстати насчёт
    var groupName = 'Employees';
    EMPLOYEES — группа в которую входят все текущие сотрудники
    РЕЗУЛЬТАТ
    ERROR: {"dn":"","code":49,"name":"InvalidCredentialsError","message":"80090308: LdapErr: DSID-0C0903A9, comment: AcceptSecurityContext error, data 52e, v1db0\u0000"}
    мда....

    Попытка потыкать второй модуль привела к тому же результату, но за большее время. Курение манов, пинание знакомого nodejs-ника и шальная удача таки дали результат: суперадмин домена почему-то не аутентифицируется, а вот бесправный юзверь, созданный ради гостевого интернета, — сработал!
    УРА


    Времени на разбирательства с правами нету — поехали дальше.
    1. git init
    2. Лицензия
    3. грязный хак для дебаггинга
      require('nw.gui').Window.get().showDevTools();
      
    4. копипаст старого кода
    ВУАЛЯ

    Можно начинать творить магию… Но уже прошёл почти час. Ребёнок может проснуться в любую минуту. Нет времени на магию — берём всё готовое.
    Быстрый гуглинг выдал на-гора отличный скрипт для работы с таблицей 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 минут…

    1. Убираем адресную строку и называем окошко
      package.json
      "window": {
        "title": "Telephone Directory",
        "toolbar": false
      }
      
    2. Автофокус на поле поиска
      users2table
      $('#query').focus();
      
    3. добавляем отдел в таблицу, а точнее — забираем не что попало, а только ФИО, телефон, емэйл, отдел
      Скрытый текст
      var ad = new ActiveDirectory(credentials.dn, credentials.dc, credentials.user, credentials.pass, {attributes: {user: [ 'cn', 'telephonenumber', 'mail', 'department']}});
      
      tablehtml+= '<td>'+user.department+'</td>'
      
    4. И раскрываем окно на весь экран, чтобы не париться по поводу размеров
      Скрытый текст
      require('nw.gui').Window.get().maximize();
      
    Уже весьма неплохо
    Но уже 7:30 и мне пора бежать.

    Эпизод 3: Наводим марaфет


    Во время обеда я снова вернулся к коду.
    Первым делом добавил фичу, которую обдумывал всю дорогу на работу — кеширование. Ибо каждый раз ждать загрузки (пусть и всего несколько секунд) глядя на пустое окно — раздражает.
    КОД
    в событие получения ответа от ldap поменял это:
    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 ссылки для емейлов… В принципе всё.
    ГОТОВО!
    Как раз и обед закончился.
    Но данный функционал уже полностью покрывает все мои планы, так что на этом я пока и остановился.

    Установка


    1. поставьте node-webkit
    2. скачайте релиз
    3. поместите файл private.js
      содержание
      module.exports = {
           dn:"ldap://example.com"
          ,dc:"dc=example,dc=com"
          ,user:"user"
          ,pass:"pass"
      };
      
    4. запускайте
      path\to\nodewebkit\nw.exe path\to\telephone-directory
      


    Распространение


    1. Запакуйте каталог telephone-directory в .zip
    2. Переименуйте архив в .nw
    3. Немного магии
      copy /b path\to\nodewebkit\nw.exe+path\to\telephone-directory telephone-directory.exe
      
    4. докиньте все остальные файлы из node-webkit кроме nw.exe в каталог с telephone-directory.exe

    Должно получиться так:

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

    P.S.

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

    P.P.S.

    Приложение рассчитано на контору с около 100 сотрудниками (вроде той в которой я работаю). При меньшем количестве вряд ли используется AD. А при большем — может потребоваться какая-то оптимизация кода, но наверняка уже используется корп-портал или что-то подобное.

    P.P.P.S.

    Кода 45 строк, так что уверен, даже для сисадминов не знающих JS, подгонка проекта под свои нужды не составит труда.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 31

      0
      Есть у нас в организации подобный проект телефонного справочника. И казалось бы задача тривиальная, НО:
      1. В организации около 6-8 зданий распределенных в пределах города, не все пользователи имеют учетки в AD, но быть в справочнике они должны;
      2. В AD по умолчанию ограничена длина полей 64 байтами, а в справочники они должны выводиться полностью. Например, есть у нас в организации такая должность: «Заместитель начальника отдела по администрированию и обеспечению безопасности системных, телекоммуникационных и программно-технических комплексов» или департамент «Братская городская общественная организация ветеранов (пенсионеров) войны, труда, Вооруженных сил и правоохранительных органов»;
      3. У пользователя может быть больше одного телефона, может быть факс и др.;
      4. Один телефон может быть у множества пользователей (виртуальные телефонные линии).

      В итоге казалось бы простая задача оказалась не такой уж простой и свелась к мерджингу информации по пользователем из АТС и AD.
        +1
        У Вас проблема тока во 2-ом пункте. Действительно, то что поле с ограничениями это минус. Порой должности и правда длинные бывают — приходится сокращать.
        В первом пункте можно создать не пользователя AD, а контакт, куда занести все его данные.
        По третьему пункту, то тут полей для телефона тоже хватает. Их шесть штук разых, есть и факс и IP-телефония и прочее. + насколько я помню атрибутах есть 15 пустых полей, в которые можно внести свободную инфу.
        Четвертый пункт так же насколько мне известно не проблемный и LDAP книга нормально отображает контакты с одинаковыми телефонами.
          0
          Внушительно.
          1: почему-бы не завести всем пользователям учётки в AD? У меня даже у уборщицы учётка есть. Разумеется она ей не пользуется, но зато структура пользователей в AD соответствует реальной структуре сотрудников организации.
          3: не пойму
          в чём проблема?

          4: А тут уже что мешает написать 1 и тот же телефон нескольким сотрудникам? У нас так обычно по телефону на отдел.

          2: Да тут конечно печально. Читал как-то про возможность снимать это ограничение (во всяком случае для отчества). Или как вариант использовать в ад коды или сокращённые названия отделов и держать базу расшифровок. Так или иначе тем кто будет это реализовывать моя поделка писанная на коленке нафиг не сдалась (:
            0
            В пункте 3 и 4 нет никаких проблем, если данные брать только из AD, но если их мерджить с АТС (в которой одна телефонная линия может соответствовать 0-n пользователям в AD, то возникают проблемы). А мерджинг используется, потому что в АТС нет ограничения на длину должности, отдела и прочих полей, но при этом в АТС есть не все пользователи (на одну виртуальную линию может приходится до нескольких десятков пользователей).
            Самый простой вариант в этом случае — это увеличить длину полей, хранимых в AD и брать данные только из AD, но отдел сетевых технологий в нашей организации на отрез отказался от этой идеи, пришлось вот так изголяться =)
            0
            Пункт 2 — ограничение схемы AD UTF 128 символов, что в русском языке = 64 символа. В схеме поменяйте длину атрибута
              0
              Как я написал выше «отдел сетевых технологий в нашей организации на отрез отказался от этой идеи», ссылаясь на то, что это потенциально может вызвать проблемы при обновлении AD на более новую версию. К сожалению я не администратор, а поверхностный поиск в google не дал ответа, может ли увеличение длины атрибута как-то выйти боком сейчас или в будущем. Если у Вас есть опыт в этом вопросе или достоверные источники, с радостью бы почитал =)
                0
                Как по мне, так любые игры с базовыми атрибутами AD могут выйти боком в будущем.
            0
            Cannot find module 'activedirectory'. Как бороться?
              0
              npm install activedirectory
              
                0
                странно, не знал что github вырезает модули. сейчас добавлю в релиз zip с модулем
              0
              Простите, что-то не уловил, а чем вам не устроил встроенный в Outlook? Почтой же, наверняка, все пользуются и скорее всего именно в нём?
              Вполне готовое и работоспособное решение…
              скриншот

                +3
                Ожидал этого комментария.
                Да почтой пользуются.
                Нет не в нём.
                По историческим и политическим причинам используется Lotus с Domino не интегрированным с AD. Но даже интегрированный с AD лотус требует очень сложного программерского допила напильником для отображения телефонного справочника. А навыков написания ПО под платформу Domino у меня нету.
                0
                Мы пользуемся «C:\Program Files\Windows Mail\wab.exe» /find
                  +1
                  А для кого сделан этот справочник?
                  Если это для себя или других системных администраторов, то красивые колки с сортировкой можно получить с помощью базовой оснастоки.
                  Немного настроенной под себя
                  .
                  image

                  Если это для быстрого доступа к справочнику без оснасток с расширением функционала, например себе или линии поддержки, то как-то скудно
                  Небольшой пример
                  image
                  Не сочтите за рекламу, но я ожидал что-то вроде такого. Сделал для саппорта.

                  Ведь для быстрого поиска с любого компьютера, да с сортировкой, можно воспользоваться такой командой как:
                  wab /find
                  . К почтовой программе это не привязано.
                  Стандартная утилита
                  image

                  Не совсем понятны цели, как справочник слишком мало полезных функций. Если только показать возможности node-webkit.

                  Да, Вы сказали серверный вариант на php, случайно не про https://github.com/tdvsdv/eight? Веб сервис с возможностью генерации автономной адресной книги.
                    –1
                    1. Сам вечно сижу с постоянно открытой оснасткой пользователи и компьютеры. Но этот справочник для всех сотрудников. На замену .xls файлу который с переменным успехом пытается актуализировать секретарь.
                    2. Круто конечно, Но нет. Просто телефонный справочник. Ничего больше. а ваша разработка дорого стоит? Взял бы себе на вооружение
                    3. Только из комментариев к этой статье узнал об этом софте :-) обязательно ознакомлюсь
                    4. Да. Спасибо.
                      0
                      Понятно. Если это для всех пользователей и все они внесены в AD, то хорошо.
                      Но к сожалению, обычно ситуация такова, что у АТС есть своя база и совпадает она с пользовательской частично. А поддерживать актуальность в ручную накладно. Тут уже или автоматизация с созданием контактов в AD, или использовать приложение/сервис где данные удобно предоставляются пользователю.

                      Моя разработка бесценна ;-), но если хотите, можете пользоваться на здоровье.
                      Исходник на D7 не выкладываю, там ничего сложного. Но если кому очень нужно, могу отдать (в приват).
                      0
                      А в wab.exe можно изменить форму, как это делается для поиска в Outlook?
                        0
                        Как я понял, в wab.exe — нельзя даже размер по умолчанию поля телефона поменять. А значит каждый грёбанный раз сдвигать эту грёбанную границу столбца вправо. Именно из-за этого я и отказался от крутого телефонного справочника рассмотренного в примерах.
                          0
                          И правда размеры столбцов не запоминаются, но хотя бы само окно при перезапуске менять не надо.
                      0
                      Пользуюсь таким pitin.su/news-155-0-0.htm.
                      Удобная штука.
                        0
                        а что там? сайт не работает
                          0
                          Видно уже не работает
                            0
                            выглядит таким образом — image
                              0
                              Это сайт веб-сервиса, не работает, да…
                              Я уже давал ссылку на гит этого проекта выше.
                          • UFO just landed and posted this here
                              0
                              1. Где вы тут сервер увидели?
                              2. Библиотека только 1 — activedirectory.
                              3. Скажу вам по секрету — использование распространённых опенсорс библиотек наоборот повышает читаемость и переиспользуемость кода, в отличие от своих велосипедов.
                              4. Умещайте. Кто ж вам мешает?
                              • UFO just landed and posted this here
                                  –1
                                  Угу, и лапша из кода, которую невозможно читать.
                                  • UFO just landed and posted this here
                                    • UFO just landed and posted this here

                            Only users with full accounts can post comments. Log in, please.