internal static async Task <JObject> SyncRoleAsync(this RequestInfo requestInfo, CancellationToken cancellationToken = default) { var data = requestInfo.GetBodyExpando(); var role = await data.Get <string>("ID").GetRoleByIDAsync(cancellationToken).ConfigureAwait(false); if (role == null) { role = Role.CreateInstance(data); await Role.CreateAsync(role, cancellationToken).ConfigureAwait(false); } else { role.Fill(data); await Role.UpdateAsync(role, true, cancellationToken).ConfigureAwait(false); } // clear related cache if (requestInfo.GetHeaderParameter("x-converter") != null) { role.ClearRelatedCacheAsync(null, ServiceBase.ServiceComponent.CancellationToken, requestInfo.CorrelationID).Run(); } else { await role.ClearCacheAsync(cancellationToken, requestInfo.CorrelationID).ConfigureAwait(false); } // send update messages var json = role.Set().ToJson(); var objectName = role.GetTypeName(true); await Task.WhenAll( Utility.RTUService.SendUpdateMessageAsync(new UpdateMessage { Type = $"{requestInfo.ServiceName}#{objectName}#Update", Data = json, DeviceID = "*" }, cancellationToken), Utility.RTUService.SendInterCommunicateMessageAsync(new CommunicateMessage(requestInfo.ServiceName) { Type = $"{objectName}#Update", Data = json, ExcludedNodeID = Utility.NodeID }, cancellationToken) ).ConfigureAwait(false); // return the response return(new JObject { { "Sync", "Success" }, { "ID", role.ID }, { "Type", objectName } }); }
internal static async Task <JObject> CreateRoleAsync(this RequestInfo requestInfo, bool isSystemAdministrator = false, Func <RequestInfo, CancellationToken, Task> serviceCaller = null, Action <RequestInfo, string, Exception> onServiceCallerGotError = null, CancellationToken cancellationToken = default) { // prepare var request = requestInfo.GetBodyExpando(); var organizationID = request.Get <string>("SystemID") ?? requestInfo.GetParameter("x-system-id") ?? requestInfo.GetParameter("SystemID"); var organization = await(organizationID ?? "").GetOrganizationByIDAsync(cancellationToken).ConfigureAwait(false); if (organization == null) { throw new InformationInvalidException("The organization is invalid"); } // check permission var gotRights = isSystemAdministrator || requestInfo.Session.User.IsModerator(null, null, organization, requestInfo.CorrelationID); if (!gotRights) { throw new AccessDeniedException(); } // create new var role = request.CreateRoleInstance("SystemID,Privileges,OriginalPrivileges,Created,CreatedID,LastModified,LastModifiedID", obj => { obj.ID = string.IsNullOrWhiteSpace(obj.ID) || !obj.ID.IsValidUUID() ? UtilityService.NewUUID : obj.ID; obj.SystemID = organization.ID; obj.ParentID = obj.ParentRole != null ? obj.ParentID : null; obj.Created = obj.LastModified = DateTime.Now; obj.CreatedID = obj.LastModifiedID = requestInfo.Session.User.ID; obj._childrenIDs = new List <string>(); }); await Role.CreateAsync(role, cancellationToken).ConfigureAwait(false); role.Set().ClearRelatedCacheAsync(null, ServiceBase.ServiceComponent.CancellationToken, requestInfo.CorrelationID).Run(); // update users 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) { { "AddedRoles", new[] { role.ID }.ToJArray().ToString(Formatting.None).Encrypt(Utility.EncryptionKey) } } }; var userIDs = role.UserIDs ?? new List <string>(); var parentRole = role.ParentRole; while (parentRole != null) { userIDs = userIDs.Concat(parentRole.UserIDs ?? new List <string>()).ToList(); parentRole = parentRole.ParentRole; } await userIDs.Distinct(StringComparer.OrdinalIgnoreCase).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); // update parent var updateMessages = new List <UpdateMessage>(); var communicateMessages = new List <CommunicateMessage>(); var objectName = role.GetTypeName(true); if (role.ParentRole != null) { await role.ParentRole.FindChildrenAsync(cancellationToken).ConfigureAwait(false); role.ParentRole._childrenIDs.Add(role.ID); await role.ParentRole.SetAsync(true, cancellationToken).ConfigureAwait(false); // message to update to all connected clients var json = role.ParentRole.ToJson(true, false); updateMessages.Add(new UpdateMessage { Type = $"{requestInfo.ServiceName}#{objectName}#Update", Data = json, DeviceID = "*" }); // message to update to all service instances (on all other nodes) communicateMessages.Add(new CommunicateMessage(requestInfo.ServiceName) { Type = $"{objectName}#Update", Data = json, ExcludedNodeID = Utility.NodeID }); } // message to update to all other connected clients var response = role.ToJson(); if (role.ParentRole == null) { updateMessages.Add(new UpdateMessage { Type = $"{requestInfo.ServiceName}#{objectName}#Create", Data = response, DeviceID = "*" }); } // message to update to all service instances (on all other nodes) communicateMessages.Add(new CommunicateMessage(requestInfo.ServiceName) { Type = $"{objectName}#Create", Data = response, ExcludedNodeID = Utility.NodeID }); // send the 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("Create", organization.Notifications, ApprovalStatus.Draft, ApprovalStatus.Published, requestInfo, ServiceBase.ServiceComponent.CancellationToken).Run(); // response return(response); }