static async Task <Tuple <List <UpdateMessage>, List <CommunicateMessage> > > DeleteChildrenAsync(this Role role, RequestInfo requestInfo, Func <RequestInfo, CancellationToken, Task> serviceCaller = null, Action <RequestInfo, string, Exception> onServiceCallerGotError = null, CancellationToken cancellationToken = default) { var updateMessages = new List <UpdateMessage>(); var communicateMessages = new List <CommunicateMessage>(); var objectName = role.GetTypeName(true); var children = await role.FindChildrenAsync(cancellationToken).ConfigureAwait(false); await children.ForEachAsync(async child => { var messages = await child.DeleteChildrenAsync(requestInfo, serviceCaller, onServiceCallerGotError, cancellationToken).ConfigureAwait(false); updateMessages = updateMessages.Concat(messages.Item1).ToList(); communicateMessages = communicateMessages.Concat(messages.Item2).ToList(); }, true, false).ConfigureAwait(false); await Role.DeleteAsync <Role>(role.ID, requestInfo.Session.User.ID, cancellationToken).ConfigureAwait(false); await role.ClearCacheAsync(cancellationToken, requestInfo.CorrelationID, true).ConfigureAwait(false); // send notification role.SendNotificationAsync("Delete", role.Organization.Notifications, ApprovalStatus.Published, ApprovalStatus.Published, requestInfo, ServiceBase.ServiceComponent.CancellationToken).Run(); // update users var beRemovedUserIDs = role.UserIDs ?? new List <string>(); var parentRole = role.ParentRole; while (parentRole != null) { beRemovedUserIDs = beRemovedUserIDs.Concat(parentRole.UserIDs ?? new List <string>()).ToList(); parentRole = parentRole.ParentRole; } beRemovedUserIDs = beRemovedUserIDs.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); var requestUser = new RequestInfo(requestInfo) { ServiceName = "Users", ObjectName = "Privileges", Verb = "POST", Query = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { "related-service", requestInfo.ServiceName }, { "related-object", "Role" }, { "related-system", role.SystemID }, { "related-entity", typeof(Role).GetTypeName() }, { "related-object-identity", role.ID } }, Extra = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { "RemovedRoles", new[] { role.ID }.ToJArray().ToString(Formatting.None).Encrypt(Utility.EncryptionKey) } } }; await beRemovedUserIDs.ForEachAsync(async userID => { try { requestUser.Query["object-identity"] = userID; await(serviceCaller == null ? Task.CompletedTask : serviceCaller(requestUser, cancellationToken)).ConfigureAwait(false); } catch (Exception ex) { onServiceCallerGotError?.Invoke(requestUser, $"Error occurred while updating roles of an user account [{userID}] => {ex.Message}", ex); } }, true, false).ConfigureAwait(false); var json = role.ToJson(); updateMessages.Add(new UpdateMessage { Type = $"{requestInfo.ServiceName}#{objectName}#Delete", Data = json, DeviceID = "*" }); communicateMessages.Add(new CommunicateMessage(requestInfo.ServiceName) { Type = $"{objectName}#Delete", Data = json, ExcludedNodeID = Utility.NodeID }); return(new Tuple <List <UpdateMessage>, List <CommunicateMessage> >(updateMessages, communicateMessages)); }
internal static async Task <JObject> DeleteRoleAsync(this RequestInfo requestInfo, bool isSystemAdministrator = false, Func <RequestInfo, CancellationToken, Task> serviceCaller = null, Action <RequestInfo, string, Exception> onServiceCallerGotError = null, CancellationToken cancellationToken = default) { // prepare var role = await(requestInfo.GetObjectIdentity() ?? "").GetRoleByIDAsync(cancellationToken).ConfigureAwait(false); if (role == null) { throw new InformationNotFoundException(); } else if (role.Organization == null) { throw new InformationInvalidException("The organization is invalid"); } // check permission var gotRights = isSystemAdministrator || requestInfo.Session.User.IsAdministrator(null, null, role.Organization, requestInfo.CorrelationID); if (!gotRights) { throw new AccessDeniedException(); } var updateMessages = new List <UpdateMessage>(); var communicateMessages = new List <CommunicateMessage>(); var objectName = role.GetTypeName(true); var updateChildren = requestInfo.Header.TryGetValue("x-children", out var childrenMode) && "set-null".IsEquals(childrenMode); // delete var children = await role.FindChildrenAsync(cancellationToken).ConfigureAwait(false); await children.ForEachAsync(async child => { // update children to root if (updateChildren) { child.ParentID = null; child.LastModified = DateTime.Now; child.LastModifiedID = requestInfo.Session.User.ID; await Role.UpdateAsync(child, requestInfo.Session.User.ID, cancellationToken).ConfigureAwait(false); child.Set().ClearRelatedCacheAsync(null, ServiceBase.ServiceComponent.CancellationToken, requestInfo.CorrelationID).Run();; child.SendNotificationAsync("Update", child.Organization.Notifications, ApprovalStatus.Published, ApprovalStatus.Published, requestInfo, ServiceBase.ServiceComponent.CancellationToken).Run(); var json = child.ToJson(true, false); updateMessages.Add(new UpdateMessage { Type = $"{requestInfo.ServiceName}#{objectName}#Update", Data = json, DeviceID = "*" }); communicateMessages.Add(new CommunicateMessage(requestInfo.ServiceName) { ServiceName = requestInfo.ServiceName, Type = $"{objectName}#Update", Data = json, ExcludedNodeID = Utility.NodeID }); } // delete children else { var messages = await child.DeleteChildrenAsync(requestInfo, serviceCaller, onServiceCallerGotError, cancellationToken).ConfigureAwait(false); updateMessages = updateMessages.Concat(messages.Item1).ToList(); communicateMessages = communicateMessages.Concat(messages.Item2).ToList(); } }, true, false).ConfigureAwait(false); await Role.DeleteAsync <Role>(role.ID, requestInfo.Session.User.ID, cancellationToken).ConfigureAwait(false); await role.ClearCacheAsync(cancellationToken, requestInfo.CorrelationID, true).ConfigureAwait(false); // update users var beRemovedUserIDs = role.UserIDs ?? new List <string>(); var parentRole = role.ParentRole; while (parentRole != null) { beRemovedUserIDs = beRemovedUserIDs.Concat(parentRole.UserIDs ?? new List <string>()).ToList(); parentRole = parentRole.ParentRole; } beRemovedUserIDs = beRemovedUserIDs.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); var requestUser = new RequestInfo(requestInfo) { ServiceName = "Users", ObjectName = "Privileges", Verb = "POST", Query = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { "related-service", requestInfo.ServiceName }, { "related-object", "Role" }, { "related-system", role.SystemID }, { "related-entity", typeof(Role).GetTypeName() }, { "related-object-identity", role.ID } }, Extra = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase) { { "RemovedRoles", new[] { role.ID }.ToJArray().ToString(Formatting.None).Encrypt(Utility.EncryptionKey) } } }; await beRemovedUserIDs.ForEachAsync(async userID => { try { requestUser.Query["object-identity"] = userID; await(serviceCaller == null ? Task.CompletedTask : serviceCaller(requestUser, cancellationToken)).ConfigureAwait(false); } catch (Exception ex) { onServiceCallerGotError?.Invoke(requestUser, $"Error occurred while updating roles of an user account [{userID}] => {ex.Message}", ex); } }, true, false).ConfigureAwait(false); // message to update to all other connected clients var response = role.ToJson(); updateMessages.Add(new UpdateMessage { Type = $"{requestInfo.ServiceName}#{objectName}#Delete", DeviceID = "*", Data = response }); // message to update to all service instances (on all other nodes) communicateMessages.Add(new CommunicateMessage(requestInfo.ServiceName) { Type = $"{objectName}#Delete", Data = response, ExcludedNodeID = Utility.NodeID }); // send update messages await Task.WhenAll( updateMessages.ForEachAsync(message => Utility.RTUService.SendUpdateMessageAsync(message, cancellationToken), true, false), communicateMessages.ForEachAsync(message => Utility.RTUService.SendInterCommunicateMessageAsync(message, cancellationToken)) ).ConfigureAwait(false); // send notification role.SendNotificationAsync("Delete", role.Organization.Notifications, ApprovalStatus.Published, ApprovalStatus.Published, requestInfo, ServiceBase.ServiceComponent.CancellationToken).Run(); // response return(response); }