“Access Denied” para BreakRoleInheritance usando RunWithElevatedPrivileges delegate
Una de las últimas cosas en las que tuve que trabajar fue con sharepoint, al tratar de personalizar el panel de discusión para que se pudiera otorgar permisos a los usuarios que se seleccionaran mediante una webpart creada por un colega. No podía usuar la habilitacion de audiencia porque necesitaba usar un buscador personalizado, asi que la opción era programar mi propio campo audiencia y controlar los eventos (added-adding-adited-aditing) para que al crear un nuevo post o tema, se otorgaran los permisos a una audiencia determinada.
Problema:
Mi problema no era con el CustomFieldType si no que con el EventHandler que estaba controlando en donde uno de los pasos era remover todos los niveles de permisos sobre un SPListItem.
Mi requerimiento consistia en dar permisos solo a usuarios y grupos particulares sobre un item y quitar el resto.
El primer dolor de cabeza fue encontrar la forma de quitar todos los permisos sobre un item para luego darle los permisos sobre los usuarios y grupos que yo quisiera.
Hasta que encontre dos maneras de hacerlo:
Forma1:
for (int k = item.RoleAssignments.Count - 1; k >= 0; k--)
{
item.RoleAssignments.Remove(k);
}
Forma2:
foreach (SPRoleAssignment spra in item.RoleAssignments) {
spra.RoleDefinitionBindings.RemoveAll();
spra.Update();
}
//donde item es un objeto SPListItem sobre el cual queremos remover los permisos
//por tema de rendimiento y optimizacion en el uso de recursos, la forma1 es recomendada
Mi segundo dolor de cabeza fue la exception que se generaba dentro de un método delegado que declaraba usando el método RunWithElevatedPrivileges() dentro de un EventHandler que habia generado para el evento ItemAdded() de un Panel de Discusión.
El código corria sin problemas cuando el evento ItemAdded() era generado por el administrador, pero levantaba una exception para cualquier otro usuario aún cuando esos otros usuarios tenian permisos de “Full Control” sobre la lista.
El problema principalmente era de permisos al ejecutar item.RoleAssignments.Remove(k) o spra.RoleDefinitionBindings.RemoveAll() ya que por mucho que definiera la ejecución con RunWithElevatedPrivileges() necesitaba manejar una serie de reglas para que todo funcionara bien.
Donde esta el problema:
Resulta que el método BreakRoleInheritance() resetea el parametro AllowUnsafeUpdates a False, del objeto SPWeb y de la propiedad Web del objeto SPListItem con lo cual obtienes un lindo security exception en tu cara.
Necesitas setear AllowUnsafeUpdates = true directamente despues de un BreakRoleInheritance, y especificamente, si es que puedes hacerlo, sobre la propiedad Web del SPListItem.
Algo super importante es que no uses ningun objeto creado fuera del RunWithElevatedPrivileges ya que los objetos SP tienen su propio security context. Trata de usar guids/urls/ids o lo que sea, pero siempre recrea los objetos dentro del metodo RunWithElevatedPrivileges.
Aca dejo los procedimientos y funciones usadas en mi solución:
Public Overrides Sub ItemAdded(ByVal properties As SPItemEventProperties) _properties = properties SPSecurity.RunWithElevatedPrivileges(New SPSecurity.CodeToRunElevated(AddressOf ManagePermissionItem)) End Sub
Public Sub ManagePermissionItem()
Try
Dim _webInUserContext As SPWeb = _properties.OpenWeb()
Dim _siteInUserContext As SPSite = New SPSite(_properties.SiteId)
Dim _itemInUserContext As SPListItem = _properties.ListItem
Dim _webGuid As Guid = _webInUserContext.ID
Dim _siteGuid As Guid = _siteInUserContext.ID
Dim _itemGuid As Integer = _itemInUserContext.ID
Dim _site As SPSite = New SPSite(_siteGuid)
_site.AllowUnsafeUpdates = True
Dim _web As SPWeb = _site.OpenWeb(_webGuid)
_web.AllowUnsafeUpdates = True
Dim _splist As SPList = _web.Lists("Lista1")
Dim _item As SPListItem = _splist.GetItemById(_itemGuid)
_item.Web.AllowUnsafeUpdates = True
'Remover todos los permisos
RemoveAllPermissions(_web, _item)
_item.Web.AllowUnsafeUpdates = True
'Obtener Usuarios y Grupos desde campo personalizado
Dim itemValue As String = _item("Campo1").ToString()
Dim splitter As String() = New String(0) {}
Dim i As Integer = 0
splitter(0) = ","
If itemValue IsNot Nothing And itemValue String.Empty Then
Dim audiencia As String() = itemValue.Split(splitter, StringSplitOptions.RemoveEmptyEntries)
For i = 0 To audiencia.Length - 1
If True = audiencia(i).Contains("ldapmembership") Then 'Es un Usuario
'Asignar pemisos con AddPermissionUser
Dim user As SPUser = _web.AllUsers(audiencia(i))
AddPermissionUser(_web, _item, user.ID, SPRoleType.Contributor)
Else 'Es un Grupo
'Asignar permisos con AddPermissionGroup
AddPermissionGroup(_web, _item, audiencia(i), SPRoleType.Contributor)
End If
Next
AddPermissionUser(_web, _item, _properties.CurrentUserId, SPRoleType.Contributor)
End If
_web.AllowUnsafeUpdates = False
Catch generatedExceptionName As Exception
End Try
End Sub
Public Sub AddPermissionUser(ByVal web As SPWeb, ByVal item As ISecurableObject, ByVal idUser As Integer, ByVal role As SPRoleType) Dim user As SPUser = web.Site.RootWeb.AllUsers.GetByID(idUser) Dim roleDefinition As SPRoleDefinition = web.RoleDefinitions.GetByType(role) Dim roleAssignment As SPRoleAssignment = Nothing If False = item.HasUniqueRoleAssignments Then item.BreakRoleInheritance(True) web.AllowUnsafeUpdates = True End If If TypeOf item Is SPListItem Then AddPermissionUser(web, DirectCast(item, SPListItem).ParentList, idUser, SPRoleType.Guest) ElseIf TypeOf item Is SPDocumentLibrary Then AddPermissionUser(web, DirectCast(item, SPDocumentLibrary).ParentWeb, idUser, SPRoleType.Guest) ElseIf TypeOf item Is SPList Then AddPermissionUser(web, DirectCast(item, SPList).ParentWeb, idUser, SPRoleType.Guest) End If Try roleAssignment = item.RoleAssignments.GetAssignmentByPrincipal(DirectCast(user, SPPrincipal)) Catch generatedExceptionName As ArgumentException roleAssignment = New SPRoleAssignment(DirectCast(user, SPPrincipal)) End Try Try roleAssignment.RoleDefinitionBindings.Add(roleDefinition) item.RoleAssignments.Add(roleAssignment) Catch generatedExceptionName As SPException End Try 'Ahora Item posee el rol que deseamos asociarle. End Sub
Public Sub AddPermissionGroup(ByVal web As SPWeb, ByVal item As ISecurableObject, ByVal idGroup As String, ByVal role As SPRoleType) Dim group As SPGroup = web.Site.RootWeb.SiteGroups(idGroup) Dim roleDefinition As SPRoleDefinition = web.RoleDefinitions.GetByType(role) Dim RoleAssignment As New SPRoleAssignment(group) If False = item.HasUniqueRoleAssignments Then item.BreakRoleInheritance(True) web.AllowUnsafeUpdates = True End If Try RoleAssignment.RoleDefinitionBindings.Add(roleDefinition) item.RoleAssignments.Add(RoleAssignment) Catch generatedExceptionName As SPException End Try End Sub
Public Sub RemoveAllPermissions(ByVal web As SPWeb, ByVal item As ISecurableObject) Dim k As Integer = 0 Try web.AllowUnsafeUpdates = True If False = item.HasUniqueRoleAssignments Then item.BreakRoleInheritance(True) web.AllowUnsafeUpdates = True End If For Each spra As SPRoleAssignment In item.RoleAssignments spra.RoleDefinitionBindings.RemoveAll() spra.Update() Next Catch generateExceptionName As SPException End Try End Sub
About this entry
You’re currently reading ““Access Denied” para BreakRoleInheritance usando RunWithElevatedPrivileges delegate,” an entry on Código Fuente de la Vida
- Published:
- Enero 12, 2009 / 3:32 pm
- Category:
- MOSS, Sharepoint
- Tags:
- Sharepoint
No comments yet
Jump to comment form | comments rss [?] | trackback uri [?]