И снова здравствуйте, вот решил написать второй пост. При создании очередного проекта возникла потребность, ограничить доступ к элементам списка (задач), и чтобы доступ на редактирование имели только два пользователя — создатель и тот, на кого эта задача назначена, и при этом тот, на кого она назначена, не мог эту задачу удалить.
Порывшись в интернете, я обнаружил, что многие программисты вешали проверку прав пользователя на событие, и если пользователь был не тот, то просто кидали стандартное исключение 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(); } }