Security auf ListItem-Ebene
Es gibt Fälle, in denen muss man Berechtigungen für einzelne Listenelemente setzen, beispielsweise wenn es um eine Liste mit Personendaten geht.
Ich musste selbiges beispielsweise für eine Liste mit Urlaubsansprüchen machen, in der für jeden Mitarbeiter ein Datensatz mit Angabe des Vorgesetzten und seines derzeitigen Anspruches an Urlaubstagen verwaltet wurde. Diese Daten dürfen natürlich nur der Mitarbeiter und sein Vorgesetzter sehen und nur Letzterer darf diese auch bearbeiten.
Der erste Ansatz mittels Views scheiterte, da diese vom Benutzer auch selbst erstellt und geändert werden können. Doch in der API gibt es für die Objekte des Typs ListItem ein Property namens RoleAssignments. Über dieses kann man Benutzern Rollen geben und damit Zugriffsrechte zuweisen. Diese Rechte werden bereits bei der Darstellung der Liste berücksichtigt, sodass nur berechtigte Benutzer mit Lesezugriff überhaupt Elemente sehen und nur Benutzer mit Schreibrechten ein Element bearbeiten können.
Umsetzung
So viel zur Theorie, jetzt geht es in die Praxis:
Um an das ListItem überhaupt heranzukommen, benötigen wir einen EventHandler, und zwar vom Typ ItemAdded. In diesem Event Handler können wir dann mittels des folgenden Codes Rollen zuweisen:
SPListItem item = properties.ListItem; SPWeb web = properties.OpenWeb(); //Liest das Feld Mitarbeiter aus dem listItem und erstellt damit ein User-Objekt SPUser vorgesetzter = web.EnsureUser((new SPFieldLookupValue(item["Vorgesetzter"].ToString())).LookupValue); SPUser personalAbteilung = web.EnsureUser((new SPFieldLookupValue(item["Personalabteilung"].ToString())).LookupValue); //Erzeugen von Rollendefinition, einmal Leser und einmal Schreibender SPRoleDefinition RoleDefReader = web.RoleDefinitions.GetByType(SPRoleType.Reader); SPRoleDefinition RoleDefWriter = web.RoleDefinitions.GetByType(SPRoleType.Contributor); //Rollenzuweisung: Mitarbeiter bekommt Leserechte, Vorgesetzter und Personalabteilung Schreibrechte //Rollenzuweisung dem ListItem hinzufügen RoleAssReader.RoleDefinitionBindings.Add(RoleDefReader); RoleAssWriter.RoleDefinitionBindings.Add(RoleDefWriter); RoleAssWriter2.RoleDefinitionBindings.Add(RoleDefWriter); //Wenn keine speziellen Berechtigungen auf dieses Item gesetzt sind (Vererbung) ... if (!item.HasUniqueRoleAssignments) //... durchbrechen wir die Vererbungshierarchie, ohne Berechtigungen zu kopieren item.BreakRoleInheritance(false); item.RoleAssignments.Add(RoleAssReader); item.RoleAssignments.Add(RoleAssWriter); item.RoleAssignments.Add(RoleAssWriter2); item.Update();
Diese obigen Zeilen sollten eigentlich ausreichend kommentiert sein. Um auch bei Änderungen an dem Item die Rollen updaten zu können, muss man natürlich entsprechenden Code auch für das Event ItemUpdated anpassen.
Der Grund dafür, dass ich statt ItemUpdating das asynchrone Event ItemUpdated verwendet habe, liegt darin, dass im ersteren Fall das Item noch nicht erzeugt wurde und damit habe ich noch keine Möglichkeit Rollen zuzuweisen. Weder RoleAssigments noch die bei Tasks verfügbaren SpecialPermissions sind in diesem Zustand bereits verwendbar.