суббота, февраля 28, 2009

PS и WSS 3

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

   1:  function ApproveItemContent {
2: if (-not $list.EnableModeration ){ return; }
3: if ($item.ModerationInformation.Status –eq
Microsoft.SharePoint.SPModerationStatusType]::Approved `
4: -or `
5: $item.ModerationInformation.Status –eq
Microsoft.SharePoint.SPModerationStatusType]::Denied)
6: { return; }
7: $this.DisableEventFiring()
8: try{
9: $item.ModerationInformation.Status = `
10: [Microsoft.SharePoint.SPModerationStatusType]::Approved;
11: $item.ModerationInformation.Comment = 'Approved with PS-script by user '
12: + $user.Name + ' at ' + [System.DateTime]::Now.ToString();
13: $item.SystemUpdate();
14: }catch{
15: # не очень и хотелось...
16: }
17: }

Эту функцию записываем в конец заготовки обработчика и ставим её вызов в обработчики добавления и обновления:


function ItemAdded{ ApproveItemContent; }
function ItemUpdated{ ApproveItemContent; }
Не обошлось, как водится, без сюрпризовsmile_nerd: на списке вики-страниц ( узел создавался с шаблоном “вики”) скрипт работает наполовину – комментарий (строка 11) записывается, а статус (строка 9) – нет. При расследовании выяснилось, что исправляет дело замена SystemUpdate() на Update() в строке 13.

Technorati Tags: ,

пятница, февраля 27, 2009

PS и WSS 2

Во второй серии балета экспериментов пытаемся сделать при помощи PS-технологии нечто содержательное. Например, достаточно часто требуется для элементов списка (документов библиотеки) оставить доступ только создателю и некоторым группам пользователей, отобрав его у всех остальных. Достаточно легко эта операция проделывается при помощи рабочего процесса с использованием activities из пакета Useful Sharepoint Designer Custom Workflow Activities. Алгоритм достаточно простой:

  1. Убрать наследование разрешений
  2. Установить разрешения для групп
  3. Установить разрешения для создателя.

Для использования в обработчике событий PowerEventReceivers имеет смысл написать функцию, выполняющую нужные действия, и вызывать её из обработчиков ItemAdded и ItemUpdated. Функция получается такая:

function ResetPermissions{
$groupsNames = "Администрация", "ИТ Отдел";
$permissionLevelName = "Полный доступ";
$permissionLevel = $null;
$mustSave=$false;
if( -not $item.HasUniqueRoleAssignments){
try{ $item.BreakRoleInheritance($false); }
catch{
# у пользователя нет нужных разрешений
return;
}
}
if($item.HasUniqueRoleAssignments){
try{
$permissionLevel = $web.RoleDefinitions[$permissionLevelName];
}catch{
# у пользователя нет разрешений или неверно задан уровень
}
if($permissionLevel -ne $null){
try{
foreach ($groupName in $groupsNames) {
$group = $null;
try{$group = $web.Groups[$groupName];}catch{} #on web
if($group -eq $null) {try{$group = $web.Site.Rootweb.Groups[$groupName];}catch{}} #on site
if($group -eq $null) {continue;} #wrong group
$role = New-Object -TypeName Microsoft.SharePoint.SPRoleAssignment -ArgumentList $group;
$role.RoleDefinitionBindings.Add($permissionLevel);
$item.RoleAssignments.Add($role);
$mustSave=$true;
}
}catch{
if(-not $mustSave){
return;
}
}
#Creator
try{
$user = (($item.Fields[[Microsoft.SharePoint.SPBuiltInFieldId]::Author] `
-as [Microsoft.SharePoint.SPFieldUser]).GetFieldValue($item[[Microsoft.SharePoint.SPBuiltInFieldId]::Author].ToString()) `
-as [Microsoft.SharePoint.SPFieldUserValue]).User;
$userRole = New-Object -TypeName Microsoft.SharePoint.SPRoleAssignment -ArgumentList $user; #SPRoleAssignment
$userRole.RoleDefinitionBindings.Add($permissionLevel);
$item.RoleAssignments.Add($userRole);
$mustSave=$true;
}catch{
if(-not $mustSave){
return;
}
}
}
if($mustSave){ # сохранить изменения
$item.SystemUpdate();
}
}
## End of ResetPermissions ##
}

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

Выходов, как обычно, находится два: заставить изменить элемент пользователя с нужными правами или применить другие средства. Можно, например, в списке настроить обязательное утверждение элементов, и в момент утверждения все необходимые действия будут выполнены.

Из “других” средств можно применить SharePoint Designer PowerActivity того же автора. В рабочем процессе, основанном на этой “активности”, можно применить тот же самый скрипт, что и в обработчике событий. С учётом того, что рабочие процессы выполняются в контексте системной учётной записи, изменения проходят у любого пользователя, имеющего разрешения на добавление и/или редактирование элементов списков. Платой за это служит необходимость иметь SPD.

Тексты скриптов для обработчика (RecieverScript.ps1) и для PowerActivity (WFScript.ps1) можно взять здесь.


Technorati Tags: ,

вторник, февраля 24, 2009

PS и WSS

В то время как по всей России страдают многие энтузиасты ратуют за использование PowerShell в деле борьбы работы с Шарепойнтом, как-то у меня самого дальше советов пользователям форума пока не продвинулось. smile_embaressed Надо восполнить пробел…

Первая серия экспериментов – с обработчиком событий iLoveSharePoint.PowerEventReceivers, представленным Christian’ом Glessner’ом (http://www.iLoveSharePoint.com). Задача – попробовать, легко ли писать скрипты для этого обработчика и как эти скрипты должны выглядеть. Содержательно – скрипты должны добавлять свои сообщения в предназначенное для этого поле.

Результат: скрипты писать легко и просто, совсем как в Студии на C#, но можно и не обращать внимания на регистр символов (спасибо MS за любовь к BASIC’у). Вид же скриптов сильно зависит от типа обработчика (вызов перед началом события/после события). Гугль подсказывает, что народ с этим постоянно сталкивается и пытается бороться. Поэтому просто примем это за реальность и правила будем использовать такие:

  • в методах, вызываемых перед началом события (ItemAdding, ItemUpdating и т.п.) работаем с After-свойствами:
    function ItemAdding{
    $message="Adding;"; $fieldName="msg";
    $internalFieldName=$list.Fields[$fieldName].InternalName;
    $properties.AfterProperties[$internalFieldName]+=$message;
    }

  • В методах, вызываемых после события (ItemAdded, ItemUpdated и т.п.) работаем с полями элемента списка:
    function ItemAdded{
    $message="Added;"; $fieldName="msg";
    $internalFieldName=$list.Fields[$fieldName].InternalName;
    $item[$internalFieldName]+=$message;
    $item.SystemUpdate();
    }

Technorati Tags: ,

вторник, февраля 03, 2009

Something strange …

That day, trying to unravel the mystery of (ideally, to find workaround) on the lack of access to data on Sharepoint sites with anonymous access allowed (!?).

Here is a test console program:

using System;
using GetListDataWCF.Lists_WS; // proxy for Lists.asmx
using System.Net;
using System.Xml;

namespace GetListDataWCF {
class Program {
static void Main(string[] args) {
if (args.Length > 0)
new Test().GetData(args[0]);
else
Console.WriteLine(
"Usage:{0} <url of site>",
typeof(Test).Assembly.ManifestModule.Name);
}
}
class Test {
public void GetData(string url) {
Lists lists = new Lists();
lists.Url = url.TrimEnd("/".ToCharArray()) +
"/_vti_bin/Lists.asmx";
lists.Credentials = CredentialCache.DefaultCredentials;
XmlNode tst =null;
try {
tst = lists.GetListCollection();
Console.WriteLine(string.Format(
"success: {0} bytes", tst.OuterXml.Length));
} catch (Exception err) {
Console.WriteLine(
string.Format("error: {0}", err.Message));
}
}
}
}
The program applies to the site, the URL of which passed through the command-line switch causes the method GetListCollection () of Lists.asmx service, and if successful, displays the size of the response service (the contents of the response in this case does not matter). . Compiled software - are here. Actually, the algorithm taken from SDK, I have used it in various programs and until recently (at least until September-October 2008) was carried out successfully to all nodes, which allow anonymous access to the data.

Now, the bizarre result of the program depends on the user launching the program, and maybe even from some factors. Most often, the result is "error: The request failed with HTTP status 401: Unauthorized.", in the case of Forms-authentication - "403, forbidden". Cases of successful fulfillment of requests are rare. smile_omg In doing so, such conduct "different" only WSS-3 sites, sites WSS-2 give the data as expected.

To check you can use nodes with addresses
http://sharepoint-community.ru:55555/ (Win-authentication)
http://sharepoint-community.ru/ (Forms-authentication)
http://www.sharepointcommunity.com/ (Win-authentication)
http://new.hse.ru/sites/ibs_test/ (WSS-2 site).
At all sites allow anonymous access to the data, the successful completion of the testing program is observed only at the last node. smile_eyeroll

Very similar to the result of "improvements" in security ... thumbs_down

Technorati Tags: