Как-то раз, разрабатывая одно из решений для интеграции SharePoint и DIRECTUM, обратил внимание на то, что ряд наших веб-частей, отображающих редко изменяющуюся информацию, такую как список пользователей или номера телефонов, постоянно запрашивали данные из DIRECTUM. Естественно, возникла мысль: а что если синхронизировать данные по пользователям в нерабочее время, например, ночью, а не в час пик работы портала? Плюс этого решения очевиден: информация из DIRECTUM по пользователю будет доступна в списке SharePoint.
Что же нужно разработать в рамках этого подхода? Во-первых, необходимо доставать данные по пользователям из справочника DIRECTUM, во-вторых, «подтягивать» различную полезную информацию из AD, в-третьих, записать все данные в список SharePoint.
Для места хранения был выбран список с пользователями узла с той целью, чтобы все данные хранились в одном списке (кстати, все вышесказанное ниже относится к Windows SharePoint Services 3.0, о Microsoft Office SharePoint Server 2007 будет сказано отдельно).
Первоначально список выглядит примерно так:
Впереди нас ждут монстры в пещере: получение данных из DIRECTUM и AD, установка всего решения на ферму SharePoint. Но, благодаря толковому применению инструментов, можно превратить нашу прогулку по пещере в занимательную экскурсию.
Царь и бог: Microsoft Visual Studio 2008. Подойдет и Express вариант. Для Active Directory - AD Explorer, входит в состав утилит от Марка Руссиновича. Для тех, кто еще хочет свою жизнь провести с девушками, а не в мучениях ручной сборки cab-архивов, очень пригодится утилита WSPBuilder.
Как использовать:
Используя AD Explorer, определяем какие организационные единицы (OU) нас интересуют и названия контроллеров домена (DC). Утилита также показывает весь запрос к каталогу в строке Path: CN=здесь кто-то, OU=орг. единица, OU=орг. единица, DC=контроллер домена,
Для получения данных будем использовать .NET, а в частности, пространство имен System.DirectoryServices. Ниже приведен листинг кода:
Dim LDAPPath As String = Nothing
Dim DirEntRoot As DirectoryEntry
Dim DirSearch As DirectorySearcher
Dim SearchResults As SearchResultCollection
LDAPPath = String.Format("LDAP://OU={0},{1}", OrgUnit, DcString.ToString)
DirEntRoot = New DirectoryEntry(LDAPPath, Nothing, Nothing, AuthenticationTypes.Secure)
DirSearch = New DirectorySearcher(DirEntRoot)
DirSearch.ServerTimeLimit = Settings.SearchTimeLimit
DirSearch.Filter = "(&(objectCategory=person)(objectClass=user))"
SearchResults = DirSearch.FindAll()
DirEntRoot.Close()
В переменную LDAPPath заносим путь запроса (смотрим из Path утилиты AD Explorer). В свойстве DirSearch.Filter самого поисковика устанавливаем фильтрацию – ищем только пользователей. В результате получаем массив результата поиска, который обрабатываем нужным нам образом. В моем примере, я сделал словарь, который по ключу (имя учетной записи) содержал объект с описанием пользователя: имя учетной записи, адрес электронной почты, адрес SIP.
Гораздо более важно получать данные из DIRECTUM. В моем случае, я вытягивал данные из справочника «Работники» с использованием ОМ билдера. Какие поля справочника я «собирал»: полное имя, подразделение, должность, сетевое имя, телефон, категория и т.д. В вашем случае, этот набор может быть совершенно другим. Результат я также сформировал в виде словаря, где ключом служил логин пользователя, а значением – объект с перечисленными выше полями.
Приступим к главному блюду – SharePoint. Убеждаемся, что список указанный выше существует («Список сведений о пользователях») и у нас хватает прав на использование утилиты Stsadm (утилита администрирования SharePoint). В сам список пользователей нужно добавить колонки, в которые мы будем записывать данные из AD и DIRECTUM. Естественно, колонки должны совпадать с выгружаемыми реквизитами, т.е. для полного имени пользователя нужно создать отдельную колонку, например FullName, и так для всех остальных.
Как переписывать туда данные, оставлю на ваше усмотрение, способов куча (скажем дружно спасибо MS за хороший API): используя простой перебор элементов с помощью SPList.Items, используя CAML или же веб-сервис Lists.asmx. Как это делать, рассказывать не буду, так как это подробно освещено в MSDN и в SDK. Кроме переписывания данных, нам еще понадобятся пользовательские настройки: не будем же мы зашивать в код наши параметры AD, название сервера DIRECTUM и т.д.? Для администрирования будем использовать свою страницу администрирования SharePoint. Это обычная aspx страница, которая будет находится в %Program Files%\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\LAYOUTS\. Что она из себя представляет в разметке? Ниже приведен заголовок страницы:
<%@ Page Language="VB" MasterPageFile="~/_layouts/application.master" Inherits="SPUsersSync.UsersSynchronizing, SPUsersSync, Version=1.0.0.0, Culture=neutral, PublicKeyToken=85b141cafe87f601" %>
<%@ Register Assembly="Microsoft.Sharepoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
Namespace="Microsoft.SharePoint.WebControls" TagPrefix="sp" %>
<%@ Register TagPrefix="SPuc" TagName="InputFormSection" Src="~/_controltemplates/InputFormSection.ascx" %>
<%@ Register TagPrefix="SPuc" TagName="ButtonSection" Src="~/_controltemplates/ButtonSection.ascx" %>
Как видим, страница наследуется от application.master (который лежит в %Program Files%\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\LAYOUTS) и ссылается на сборку Microsoft.SharePoint.dll. Ниже приведена ссылка на пример моей страницы.
Страницу сделали, но до нее нужно еще добраться. Конечно, можно вбивать прямой url в адресной строке браузера, например, http://megasite/_layouts/config.aspx, но это некрасивый вариант. Я сделал доступ к странице как дополнительный пункт меню администрирования коллекции узлов (внизу):
Отдельным элементарным блоком бизнес-логики SharePoint является возможность (feature). Она может включать в себя список, рабочий процесс, веб-части, страницу и пр. Как SharePoint распознает что вот ЭТО возможность? С помощью файла feature.xml, в котором описана возможность и ссылки на другие файлы. Возможности объединяются в решения (solution), которое фактически представляет собой cab-архив с манифестом ресурсов внутри. Решение разворачивается на ферме SharePoint и позволяет централизованно управлять возможностями.
Таким образом, для нашего решения мы напишем описание возможности в виде пары xml файлов, а решение сформируем с помощью WSPBuilder (помним, что я говорил про девушек).
В студии нужно повторить структуру каталогов в %Program Files%\Common Files\Microsoft Shared\Web Server Extensions\12:
Повтор такой структуры позволит нам быть уверенным, что WSPBuilder сформирует корректный пакет решения. Что из себя представляет feature.xml? Смотрим ниже:
Id="4CB11889-49B9-478a-9D8E-FA492B2A0D68" Description="Синхронизация пользователей с AD и DIRECTUM" Hidden="False" Title="UsersSync" Scope="Site" Version="1.0.0.0">
Как видим, это описание нашего решения и ссылка на еще один файл возможности. Описание полей выходит за рамки нашего разговора, но они детально описаны как на MSDN, так и в SDK для SharePoint. А что из себя представляет UsersSync.xml? Файл похож на feature.xml:
Id="C3FC0631-5CCF-4134-8ED3-AD23F61BC35A" GroupId="SiteCollectionAdmin" Location="Microsoft.SharePoint.SiteSettings" Sequence="100" Description="Синхронизация пользователей с AD и DIRECTUM" Title="Синхронизация пользователей">
Основное внимание обращаем на элемент CustomAction – именно он описывает тот пункт меню на панели администрирования коллекцией узлов. С помощью WSPBuilder создаем WSP файл и устанавливаем его на ферму SharePoint (все делается из контекстного меню проекта в студии). В результате у вас должно получится примерно так:
Теперь насчет MOSS 2007. Он имеет самостоятельные средства интеграции с AD и, что самое интересное, позволяет добавлять свои колонки к списку пользователей, но не разрешает их изменять.
Надеюсь, изложенный выше материал, будет кому-нибудь полезен. Если у кого возникнут вопросы, то буду рад ответить :).
Авторизуйтесь, чтобы написать комментарий