Erro “Attempted to perform an unauthorized operation.” ao tentar alterar um objeto do site em um workflow no SharePoint 2010

É muito comum quando desenvolvemos para SharePoint nos depararmos com a necessidade de manipularmos alguns objetos via API, e muito mais comum ainda, é fazer essas chamadas a API a partir de uma atividade de workflow personalizada, até então tudo muito simples não é? Pois bem, embora pareça uma tarefa muito simples, tenho visto inúmeras pessoas encontrarem alguns obstáculos, e, para explicar como superar um destes obstáculos, iremos implementar a solução proposta abaixo:

Vamos supor que precisamos atribuir permissão de colaboração para um determinado grupo, em um item de uma lista (item para o qual o workflow será executado), isso realizado a partir de chamadas à API em uma atividade de workflow personalizada.


protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
    SPWeb web = SPContext.Current.Web;
    var item = SPContext.Current.ListItem;
 
    if (!item.HasUniqueRoleAssignments)
    {
        item.BreakRoleInheritance(true);
    }
 
    SPRoleDefinition role = web.RoleDefinitions["Contribute"];
 
    var roleAssignment = new SPRoleAssignment(web.Groups["MyGroup"]);
    roleAssignment.RoleDefinitionBindings.Add(role);
    item.RoleAssignments.Add(roleAssignment);
 
    return ActivityExecutionStatus.Closed;
}


Até então tudo certo, mandamos rodar o workflow e ele executa a nossa atividade. Entretanto, no momento que tentamos alterar as permissões do objeto, o seguinte erro acontece “Attempted to perform an unauthorized operation”.
Quem já está acostumado com desenvolvimento para SharePoint já deve ter se deparado com esse problema diversas vezes, e, em geral, a solução é bem simples, basta utilizar o método RunWithElevatedPrivileges da classe SPSecurity.


protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
    SPSecurity.RunWithElevatedPrivileges(() =>
    {
        SPWeb web = SPContext.Current.Web;
        var item = SPContext.Current.ListItem;
 
        if (!item.HasUniqueRoleAssignments)
        {
            item.BreakRoleInheritance(true);
        }
 
        SPRoleDefinition role = web.RoleDefinitions["Contribute"];
 
        var roleAssignment = new SPRoleAssignment(web.Groups["MyGroup"]);
        roleAssignment.RoleDefinitionBindings.Add(role);
        item.RoleAssignments.Add(roleAssignment);
    });
 
    return ActivityExecutionStatus.Closed;
}


Problema resolvido ? Errado !
Mesmo executando com privilégios elevados o erro continua, mas por que isso?
O problema é mais simples do que parece: quando utilizamos o método RunWithElevatedPrivileges o nível de permissão será aplicado a todos objetos de escopo do delegate passado como parametro, ou seja, basta criarmos as instâncias dos objetos que queremos modificar dentro do delegate que o problema será resolvido.


protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
    SPSecurity.RunWithElevatedPrivileges(() =>
    {
        using (SPSite site = new SPSite(SPContext.Current.Site.ID))
        {
            using (SPWeb elevatedWeb = site.OpenWeb(SPContext.Current.Web.ID))
            {
                var item = elevatedWeb.Lists[SPContext.Current.List.ID].Items[SPContext.Current.ListItem.UniqueId];
 
                if (!item.HasUniqueRoleAssignments)
                {
                    item.BreakRoleInheritance(true);
                }
 
                SPRoleDefinition role = elevatedWeb.RoleDefinitions["Contribute"];
 
                var roleAssignment = new SPRoleAssignment(elevatedWeb.Groups["MyGroup"]);
                roleAssignmentRevisores.RoleDefinitionBindings.Add(role);
                item.RoleAssignments.Add(roleAssignment);
            }
        }
    });
 
    return ActivityExecutionStatus.Closed;
}