Страницы

воскресенье, 18 декабря 2011 г.

Обнуление PeopleEditor

В одном из проектов потребовалось на стороне клиента, обнулить значение поля выбора пользователя (PeopleEditor)  но как оказалось это не так просто. Поковырявшись в разметке около 3х часов написал следующий код.

 if ($("div[id$='Performer_upLevelDiv']")[0].innerHTML != "") {
  $("div[id$='Performer_upLevelDiv']")[0].innerHTML = "";
  $("textarea[id$='Performer_downlevelTextBox']")[0].innerHTML = "";
  $("input[id$='Performer_hiddenSpanData']").val('');
  $("input[id$='Performer_OriginalEntities']").val('');
  $("input[id$='Performer_HiddenEntityKey']").val('');
  $("input[id$='Performer_HiddenEntityDisplayText']").val('');
  }
 Сей код полностью обнулят контрлл PeopleEditor с id = Performer, и при сабмите на сервер  контрол придет полностью пустым.

Рассылка в SharePoint

Привет всем, этим постом я начну серию по SharePoint (далее шарик), кому-то эти знания покажутся тривиальными, но мне пришлось потратить некоторое время, чтоб найти их и адаптировать по свои нужды. 
Итак, начнем. В шарике есть встроенная рассылка, когда приходят письма об определенных событиях прошедших на портале. Например, назначение задачи на пользователя или изменение статуса задачи. Можно конечно воспользоваться типами из пространства имен System.Net но в этом случае письма будут приходить не в стиле шарика.
Задача 1 предположим у нас на узле шарика есть стандартный список замечаний названный “Замечания” и нужно отправлять оповещение пользователю, на которого назначена данная задача.

            SPWeb web = new SPSite(Url  вашего сайта где находится список “Замечания”).OpenWeb();
            SPAlert alert = web.Alerts.Add();  //добавляем оповещение
            alert.Title = "Вам назначена задача"; //тут добавляем “начало” темы письма
            alert.AlertType = SPAlertType.List;  // оповещение для списка (не для конкретного элемента)
            alert.EventType = SPEventType.Add;   // cобытия на которые срабатывает alert (можно Delete, Discussion, Modify, All и Add)
            alert.AlertFrequency = SPAlertFrequency.Immediate;  // отсылать оповещение сразу (можно ежденевно, сразу, раз в неделю)
            alert.User = null; // оповещение системное, и владельца у него нет                 
            alert.AlertTemplate = new SPAlertTemplate { Name = "SPAlertTemplateType.Tasks" }; // шаблон сообщения 
            alert.List = web.Lists["Замечания"];                // список на который вешается динамическое оповещение
            alert.DynamicRecipient = "AssignedTo";             // поле, в котором указан пользователь получающий оповещение
            alert.Status = SPAlertStatus.On; //включение отключение оповещения
            alert.Update(false);  //применяем все изменения которые внесли после создания оповещения 

Подробнее о шаблонах писем тут msdn.microsoft.com/ru-ru/library/bb802738.aspx

Задача 2 нужно отправить оповещение автору задачи, если задача перешла в статус «Выполнено» или «Отклонено»

var chose = new List<string>() { "Выполнено", "Отклонено" }; 
                for (int j = 0; j < chose.Count; j++)
                {
                    SPAlert alertProblem = web.Alerts.Add();
                    alertProblem.Title = "Замечание";
                    alertProblem.AlertType = SPAlertType.List;             // оповещение для списка (не для конкретного элемента)
                    alertProblem.EventType = SPEventType.Modify;           // события на которые срабатывает alert (модификация Items)

Главное отличие этого оповещения от предыдущего это то, что нужно фильтровать события и конечно тут никуда не денешься от CAML запроса. Суть запроса фильтровать изменение в Item и если значение в поле “Status” изменилось и является одним из нужных нам («Выполнено», «Отклонено») то срабатывает оповещение. Вообще возможность применения CAML запросов делает достаточно гибким систему оповещений SharePoint.

                    alertProblem.Filter = @"" + "" +
                        "" +
                            "" +
                                chose[j] +
                            "" +
                            "" + //новое значение в поле Status
                        "" +
                        "" +
                           "" +
                               chose[j] +
                            "" +
                            "" + // значение в поле Status до изменения
                        "" +
                      "" + "";         
                    alertProblem.AlertFrequency = SPAlertFrequency.Immediate; 
                    alertProblem.User = null;                                  // оповещение системное, и владельца у него нет

                    alertProblem.AlertTemplate = new SPAlertTemplate { Name = "SPAlertTemplateType.Tasks" };
                    alertProblem.List = web.Lists["Замечания"];
                    alert.DynamicRecipient = " Author";             // поле, в котором указан пользователь получающий оповещение

                    alertProblem.Status = SPAlertStatus.On;
                    alertProblem.Update(false);
                }

Итогом всего этого будет рассылка писем в стиле SharePoint.
Данный код привязать к списку можно консольным приложением или вставив, в какое либо событие. Я его вставил в событие создание web – узла.

среда, 2 февраля 2011 г.

SharePoint и права доступа

И снова здравствуйте, вот решил написать второй пост. При создании очередного проекта возникла потребность, ограничить доступ к элементам списка (задач), и чтобы доступ на редактирование имели только два пользователя — создатель и тот, на кого эта задача назначена, и при этом тот, на кого она назначена, не мог эту задачу удалить.
Порывшись в интернете, я обнаружил, что многие программисты вешали проверку прав пользователя на событие, и если пользователь был не тот, то просто кидали стандартное исключение SharePoint о недостатке прав на данную операцию. Но мне это решение не понравилось. Покопавшись, я сделал так, что пользователь, у которого нет прав, не видит операций, которые ему запрещены.
Суть решения состоит в том, что при событиях ItemAdded и ItemUpdated я для данной конкретной записи наделяю правами нужных мне пользователей, а остальным пользователям присваиваю роль с правами только для чтения. А поскольку мне нужны специфические права (запрет удаления), мне пришлось создать отдельную роль с ограниченными правами.
Итак, теперь поподробней.




private void CreateAccess(SPItemEventProperties properties)
        { DisableEventFiring();  //данный метод присутствует в событии ItemUpdated  поэтом отключаем Updated чтоб не получить в дальнейшем зацикливание
// запись создается/редактируется под пользователем, поднимаем приоритет операций до прав админа (поскольку только он может создавать и назначать роли)            
SPSecurity.RunWithElevatedPrivileges(delegate()  
         {
                 if (properties.ListItemId != 0) 
                 {
                     SPWeb web = new SPSite(properties.WebUrl).OpenWeb();  //получаем узел 
                     SPListItem item = web.Lists[properties.ListTitle].Items.GetItemById(properties.ListItemId);  // получаем созданную запись
                    //отключаем наследование прав пользователей списка                     
                     if (!item.HasUniqueRoleAssignments) { item.BreakRoleInheritance(false); }; 

                     #region для всех пользователей и групп  узла назначаем права ридеров
                     for (int i = 0; i < web.Users.Count; i++)
                     {
                         var roleAssignment = new SPRoleAssignment(
                         web.Users[i].LoginName, 
                         web.Users[i].Email,
                         web.Users[i].Name, 
                         web.Users[i].Notes);  //добавляем пользователя в объект роли
                         roleAssignment.RoleDefinitionBindings.Add(web.RoleDefinitions.GetByType(SPRoleType.Reader));
                         //назначаем роль ридера          
                         item.RoleAssignments.Add(roleAssignment);  добавляем пользователя в «хранилище ролей» записи
                     }
                     for (int i = 0; i < web.Groups.Count; i++) // проделываем тоже самое с группами
                     {
                         var roleAssignment = new SPRoleAssignment(web.Groups[i]);

                         roleAssignment.RoleDefinitionBindings.Add(web.Groups[i].Name == "Группа админов"
                                                                       ? web.RoleDefinitions.GetByType(
                                                                           SPRoleType.Administrator)
                                                                       : web.RoleDefinitions.GetByType(SPRoleType.Reader));
                         item.RoleAssignments.Add(roleAssignment); 
                     }
                     #endregion

Здесь хочется отметить, что если для данной записи не добавить (или удалить) пользователя из «хранилища ролей» записи, то этот пользователь не увидит данной записи в списке. Что очень удобно, особенно в списке документов, когда нужно спрятать какой-то документ, например контракт.



#region назначаем права для автора и того на кого назначено задание
                     SPUser author = new SPFieldUserValue(
                                     web, 
                                     properties.ListItem["Author"].ToString()).User;
//получаем пользователя из поля автор и назначаем ему роль участник
                     SPRoleAssignment authorRoleAssignment = new SPRoleAssignment(
                                                             author.LoginName, 
                                                             author.Email, 
                                                             author.Name, 
                                                             author.Notes);
                     authorRoleAssignment.RoleDefinitionBindings.Add(web.RoleDefinitions.GetByType(SPRoleType.Contributor));
                     item.RoleAssignments.Add(authorRoleAssignment);

                     AddAccess(web);  // метод создания роли участника но без возможности удаления записи, данный метод описан ниже
                    //Далее созданную роль (Ограниченное участие)// присваиваем пользователю, на которого назначено задание
                     SPUser assignedTo = new SPFieldUserValue(
                                         web, 
                                         properties.ListItem["AssignedTo"].ToString()).User;
                     SPRoleAssignment assignedToRoleAssignment = new SPRoleAssignment(
                                                        assignedTo.LoginName, 
                                                        assignedTo.Email, 
                                                        assignedTo.Name, 
                                                        assignedTo.Notes);
                     assignedToRoleAssignment.RoleDefinitionBindings.Add(web.RoleDefinitions["Ограниченное участие"]);
                     
                     item.RoleAssignments.Add(assignedToRoleAssignment);                  
                     item.SystemUpdate(false);  //поскольку права можно назначить уже созданной записи то чтобы наши манипуляции с правами не попали в журнал версий записи вызываем данный метод
                     #endregion
}



Итак, самое интересное: создаем роль, при которой пользователь не будет видеть ни в карточке записи, ни в меню записи в представлении списка команды «удалить запись».


private void AddAccess(SPWeb web)
        {
//проверяем, не была ли роль создана ранее
            bool roleIs = false;
            foreach (SPRoleDefinition roleDefinition in web.RoleDefinitions)
            {
                if (roleDefinition.Name == "Ограниченное участие") { roleIs = true; }
            }


            if (!roleIs) //ну и если не было создано роли ранее то собственно создаем саму роль
            {
                SPRoleDefinition roleDefinition = new SPRoleDefinition()
                {
                    BasePermissions = SPBasePermissions.OpenItems |
                    SPBasePermissions.ViewListItems |
                    SPBasePermissions.AddListItems |
                    SPBasePermissions.EditListItems |
                    SPBasePermissions.OpenItems |
                    SPBasePermissions.ViewVersions |
                    SPBasePermissions.DeleteVersions |
                    SPBasePermissions.ManagePersonalViews |
                    SPBasePermissions.ViewFormPages |
                    SPBasePermissions.Open |
                    SPBasePermissions.ViewPages |
                    SPBasePermissions.CreateSSCSite |
                    SPBasePermissions.BrowseDirectories |
                    SPBasePermissions.BrowseUserInfo |
                    SPBasePermissions.AddDelPrivateWebParts |
                    SPBasePermissions.UpdatePersonalWebParts |
                    SPBasePermissions.UseClientIntegration |
                    SPBasePermissions.UseRemoteAPIs |
                    SPBasePermissions.CreateAlerts |
                    SPBasePermissions.EditMyUserInfo,
                    Name = "Ограниченное участие",
                    Description = "Все привилегии роли Участник кроме возможности удаления"
                };

                web.RoleDefinitions.BreakInheritance(true, true);
                web.RoleDefinitions.Add(roleDefinition);
                web.Update();
            }
        }


Подробное описание прав можно найти тут