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);
            }
        }
Esempio n. 2
0
        /// <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);
            }
        }