/// <summary> /// After creation adds this group to the nearest parent <see cref="OrganizationalUnit"/> as a member. /// Do not use this method directly from your code. /// </summary> protected override void OnCreated(object sender, NodeEventArgs e) { base.OnCreated(sender, e); // insert this group to the security graph using (new SystemAccount()) { var parent = GroupMembershipObserver.GetFirstOrgUnitParent(e.SourceNode); if (parent != null) { SecurityHandler.AddGroupsToGroup(parent.Id, new[] { e.SourceNode.Id }); } } var usersToAdd = GetMemberUsers().Select(u => u.Id).ToArray(); var groupsToAdd = GetMemberGroups().Select(g => g.Id).ToArray(); if (usersToAdd.Length > 0 || groupsToAdd.Length > 0) { SecurityHandler.AddMembers(this.Id, usersToAdd, groupsToAdd); } }
protected override void OnNodeMoved(object sender, NodeOperationEventArgs e) { // We do not have to deal with content outside of the IMS folder, because // moving local groups does not involve any membership change. if (!e.OriginalSourcePath.StartsWith(RepositoryStructure.ImsFolderPath + RepositoryPath.PathSeparator) && !e.SourceNode.Path.StartsWith(RepositoryStructure.ImsFolderPath + RepositoryPath.PathSeparator)) { return; } base.OnNodeMoved(sender, e); var movedUsers = new List <int>(); var movedGroups = new List <int>(); // if the moved content is an identity, put it into the appropriate list if (e.SourceNode is User) { movedUsers.Add(e.SourceNode.Id); } else if (e.SourceNode is Group || e.SourceNode is OrganizationalUnit) { movedGroups.Add(e.SourceNode.Id); } else { // If the moved content is an irrelevant container (e.g. a folder), collect relevant (first-level) child content (users, groups // and child orgunits even inside simple subfolders). These are already moved to the new location, but we only need their ids. using (new SystemAccount()) { CollectSecurityIdentityChildren(NodeHead.Get(e.SourceNode.Path), movedUsers, movedGroups); } } // empty collections: nothing to do if (movedUsers.Count == 0 && movedGroups.Count == 0) { return; } // find the original parent orgunit (if there was one) var parent = Node.LoadNode(RepositoryPath.GetParentPath(e.OriginalSourcePath)); var originalParentId = 0; var targetParentId = 0; if (parent is OrganizationalUnit) { originalParentId = parent.Id; } else { using (new SystemAccount()) { parent = GetFirstOrgUnitParent(parent); if (parent != null) { originalParentId = parent.Id; } } } // find the target parent orgunit (if there is one) using (new SystemAccount()) { parent = GetFirstOrgUnitParent(e.SourceNode); if (parent != null) { targetParentId = parent.Id; } } // remove relevant child content from the original parent org unit (if it is different from the target) if (originalParentId > 0 && originalParentId != targetParentId) { SecurityHandler.RemoveMembers(originalParentId, movedUsers, movedGroups); } // add the previously collected identities to the target orgunit (if it is different from the original) if (targetParentId > 0 && originalParentId != targetParentId) { SecurityHandler.AddMembers(targetParentId, movedUsers, movedGroups); } }
/// <summary> /// Updates the membership modifications in the sensenet security database. /// Do not use this method directly from your code. /// </summary> protected void UpdateMembership(NodeEventArgs e) { if (e.ChangedData == null) { return; } // load and parse member list var membersData = e.ChangedData.FirstOrDefault(cd => string.Compare(cd.Name, MEMBERS, StringComparison.InvariantCulture) == 0); if (membersData == null) { return; } var oldMembers = (membersData.Original as string ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(m => Convert.ToInt32(m)).ToArray(); var newMembers = (membersData.Value as string ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(m => Convert.ToInt32(m)).ToArray(); var addedIdentities = newMembers.Except(oldMembers); var removedIdentities = oldMembers.Except(newMembers); // I chose collecting arrays over LINQ here because this way we enumerate and load nodeheads only once var ntUser = ActiveSchema.NodeTypes["User"]; var ntGroup = ActiveSchema.NodeTypes["Group"]; var usersToAdd = new List <int>(); var usersToRemove = new List <int>(); var groupsToAdd = new List <int>(); var groupsToRemove = new List <int>(); // collect users and groups to add foreach (var nodeHead in addedIdentities.Select(NodeHead.Get).Where(nh => nh != null)) { if (nodeHead.GetNodeType().IsInstaceOfOrDerivedFrom(ntUser)) { usersToAdd.Add(nodeHead.Id); } else if (nodeHead.GetNodeType().IsInstaceOfOrDerivedFrom(ntGroup)) { groupsToAdd.Add(nodeHead.Id); } } // collect users and groups to remove foreach (var nodeHead in removedIdentities.Select(NodeHead.Get).Where(nh => nh != null)) { if (nodeHead.GetNodeType().IsInstaceOfOrDerivedFrom(ntUser)) { usersToRemove.Add(nodeHead.Id); } else if (nodeHead.GetNodeType().IsInstaceOfOrDerivedFrom(ntGroup)) { groupsToRemove.Add(nodeHead.Id); } } if (usersToRemove.Count > 0 || groupsToRemove.Count > 0) { SecurityHandler.RemoveMembers(this.Id, usersToRemove, groupsToRemove); } if (usersToAdd.Count > 0 || groupsToAdd.Count > 0) { SecurityHandler.AddMembers(this.Id, usersToAdd, groupsToAdd); } }
/// <summary> /// Clears the security storage copies ids of the full content tree structure from the repository /// to the security component. Security component must be available. /// WARNING! Use only in install scenarios. /// </summary> public void InstallDefaultSecurityStructure(InitialData data = null) { using (var op = SnTrace.System.StartOperation("Installing default security structure.")) { using (new SystemAccount()) { CreateEntities(); var ed = _securityHandler.CreateAclEditor(); ed.Allow(Identifiers.PortalRootId, Identifiers.AdministratorsGroupId, false, // ReSharper disable once CoVariantArrayConversion PermissionType.BuiltInPermissionTypes); var schema = _storageSchema; var memberPropertyType = schema.PropertyTypes["Members"]; var userNodeType = schema.NodeTypes["User"]; var groupNodeType = schema.NodeTypes["Group"]; if (data?.DynamicProperties != null) { foreach (var versionData in data.DynamicProperties) { if (versionData.DynamicProperties == null) { continue; } var properties = versionData.ReferenceProperties; List <int> references = null; foreach (var property in properties) { if (property.Key.Name == "Members") { references = (List <int>)property.Value; break; } } if (references == null) { continue; } var versionId = versionData.VersionId; var nodeId = data.Versions.First(x => x.VersionId == versionId).NodeId; var heads = NodeHead.Get(references); var userMembers = new List <int>(); var groupMembers = new List <int>(); foreach (var head in heads) { var nodeType = head.GetNodeType(); if (nodeType.IsInstaceOfOrDerivedFrom(userNodeType)) { userMembers.Add(head.Id); } if (nodeType.IsInstaceOfOrDerivedFrom(groupNodeType)) { groupMembers.Add(head.Id); } } _securityHandler.AddMembers(nodeId, userMembers, groupMembers); } } if (data == null) { ed.Apply(); } else { ed.Apply(ParseInitialPermissions(ed.Context, data.Permissions)); } } op.Successful = true; } }