Страницы

среда, 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();
            }
        }


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