Работа с API службы профилей пользователей SharePoint с помощью Node.js
Данная статья является логическим продолжением предыдущей публикации, где разбиралось, как работать со службой управляемых метаданных (MMD). Статья приоткрывает проблематику работы с SharePoint API средствами Node.js, а именно - работу с API очень популярного сервиса SharePoint - службами профилей пользователей (UPS).
REST интерфейс для UPS будет поинтереснее аналогичного для MMD, как минимум он есть. Разделы UPS API PeopleManager и ProfileLoader позволяют допольно много чего. Однако, как всегда не обошлось без того, что чего-то да и не хватает, не все возможности CSOM присустствуют в его аналоге на REST. Большинство методов предназначены для работы с собственным профилем и большинство свойств только на чтение.
В нашем же сценарии мы собираемся создать механизм по записи свойств в произвольные профили. Так же, как и в случае с MMD, будут задействованы SOAP службы и CSOM/JSOM интерфейс для того, чтобы расширить возможности кода на Node.js. Такой сценарий имеет место быть, если у нас есть сторонний источник данных с данными пользователей и нам надо синхронизировать эти свойства с профилями, при этом по какой-то неведомой причине условие - использовать только JavaScript для задачи, запускаемой по расписанию.
SOAP
Дедушка SOAP API в SharePoint прячется по ссылке /_vti_bin/UserProfileService.asmx
. Сервис, на самом деле, довольно большой и в нем порядка 40 методов. Ну что, весьма не дурно.
Для записи свойств нас интересует следующий метод - ModifyUserPropertyByAccountName
. Он позволяет писать одиночные и мультизначения в свойства заданного профиля.
Так же, как и в случае с MMD, для обеспечения коммуникации с SharePoint задействуем sp-request и node-sp-auth. Привет Сергею Сергееву, автору данных чудесных библиотек!
Взглянем на ModifyUserPropertyByAccountName. SOAP пакет выглядит следующим образом:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ModifyUserPropertyByAccountName
xmlns="http://microsoft.com/webservices/SharePointPortalServer/UserProfileService">
<accountName>{{ accountName }}</accountName>
<newData>
{{#newData}}
<PropertyData>
<IsPrivacyChanged>{{ isPrivacyChanged }}</IsPrivacyChanged>
<IsValueChanged>{{ isValueChanged }}</IsValueChanged>
<Name>{{ name }}</Name>
<Privacy>{{ privacy }}</Privacy>
<Values>
{{#values}}
<ValueData>
<Value xsi:type="xsd:string">{{ this }}</Value>
</ValueData>
{{/values}}
</Values>
</PropertyData>
{{/newData}}
</newData>
</ModifyUserPropertyByAccountName>
</soap:Body>
</soap:Envelope>
Динамически подставляемые параметра:
- accountName - логин пользователя (
i:0#.f|membership|user.name@contoso.com
) - newData - массив свойств
- name - имя свойства
- values - значение(я) свойства
После того, как XML безобразие обернуто в человеческий вид, работать с методом можно так:
let Screwdriver = require('sp-scredriver');
let context = require('./path_to_private_settings');
let screw = new Screwdriver(context);
let data = {
baseUrl: context.siteUrl,
accountName: config.ups.accountName,
newData: [{
isPrivacyChanged: false,
isValueChanged: true,
privacy: 'NotSet',
name: 'SPS-Birthday',
values: [ '10.03' ]
}, {
isPrivacyChanged: false,
isValueChanged: true,
privacy: 'NotSet',
name: 'SPS-Department',
values: [ 'Administration' ]
}]
};
screw.ups.modifyUserPropertyByAccountName(data)
.then(response => {
console.log('Response:', response.body);
})
.catch(err => console.log('Error:', err.message));
На этом с SOAP составляющий все. Я на самом деле, жутко не люблю SOAP. Получается дружба по принуждению, к счастью, помимо мыльца есть и альтернатива с client.svc.
CSOM/JSOM
В CSOM API присутствуют два метода по записи свойст setSingleValueProfileProperty
и setMultiValuedProfileProperty
, их-то и будем оборачивать в библиотеку. В предыдущей статье описано более подробно, в этом контексте не буду повторяться, упомяну лишь, что нужно реализовать требуемую функциональность в JSOM и посмотреть отправляемый на client.svc пакет в fiddler.
// JSOM вариант
var clientContext = new SP.ClientContext.get_current();
var peopleManager = new SP.UserProfiles.PeopleManager(clientContext);
peopleManager.setMultiValuedProfileProperty(
`i:0#.f|membership|${_spPageContextInfo.userLoginName}`,
'SPS-Skills',
[ 'Git', 'Node.js', 'JavaScript', 'SharePoint' ]
);
clientContext.executeQueryAsync(
() => console.log('Done'),
(sender, args) => console.log('Error:', args.get_message())
);
При перехвате fiddler'ом получаем пакет:
<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="15.0.0.0" ApplicationName="Javascript Library">
<Actions>
<ObjectPath Id="82" ObjectPathId="81" />
<Method Name="SetMultiValuedProfileProperty" Id="83" ObjectPathId="81">
<Parameters>
<Parameter Type="String">{{ accountName }}</Parameter>
<Parameter Type="String">{{ propertyName }}</Parameter>
<Parameter Type="Array">
{{#propertyValues}}
<Object Type="String">{{ this }}</Object>
{{/propertyValues}}
</Parameter>
</Parameters>
</Method>
</Actions>
<ObjectPaths>
<Constructor Id="81" TypeId="{cf560d69-0fdb-4489-a216-b6b47adf8ef8}" />
</ObjectPaths>
</Request>
Где:
- accountName - опять же логин (
i:0#.f|membership|user.name@contoso.com
) - propertyName - наименование свойства
- propertyValues - массив значений свойства
После обертки в библиотеку на Node.js, уже не надо думать о пакетах, а использовать следующий вызов:
let Screwdriver = require('sp-scredriver');
let context = require('./path_to_private_settings');
let screw = new Screwdriver(context);
let data = {
baseUrl: context.siteUrl,
accountName: config.ups.accountName,
propertyName: 'SPS-Skills',
propertyValues: [ 'Git', 'Node.js', 'JavaScript', 'SharePoint' ]
};
screw.ups.setMultiValuedProfileProperty(data)
.then(response => {
console.log('Response:', JSON.parse(response.body));
})
.catch(err => console.log('Error:', err.message));
setSingleValueProfileProperty практически идентичен, только проще.
Все исходники можно посмотреть на GitHub. Как уже говорил раньше, sp-screwdriver - библиотека-пример, не для "продакшена", а более как пример, но все это отражает то, как можно реализовать подобные сценарии программного взаимодействия в Node.js, когда это вдруг стало жизненно необходимо, либо Вы фанат технологии, как я.
Опубликовано: 16.02.2017
Автор: Андрей Кольтяков