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)); }
public static async Task <Role> GetRoleByIDAsync(this string id, CancellationToken cancellationToken = default, bool force = false) => (id ?? "").GetRoleByID(force, false) ?? (await Role.GetAsync <Role>(id, cancellationToken).ConfigureAwait(false))?.Set();
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); }
internal static Role Remove(this Role role) => (role?.ID ?? "").RemoveRole();
public static Role GetRoleByID(this string id, bool force = false, bool fetchRepository = true) => !force && !string.IsNullOrWhiteSpace(id) && RoleProcessor.Roles.ContainsKey(id) ? RoleProcessor.Roles[id] : fetchRepository && !string.IsNullOrWhiteSpace(id) ? Role.Get <Role>(id)?.Set() : null;
internal static async Task <JObject> UpdateRoleAsync(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.IsModerator(null, null, role.Organization, requestInfo.CorrelationID); if (!gotRights) { throw new AccessDeniedException(); } // update var oldParentID = role.ParentID; var oldUserIDs = role.UserIDs ?? new List <string>(); role.UpdateRoleInstance(requestInfo.GetBodyExpando(), "ID,SystemID,Privileges,OriginalPrivileges,Created,CreatedID,LastModified,LastModifiedID", async obj => { obj.LastModified = DateTime.Now; obj.LastModifiedID = requestInfo.Session.User.ID; await obj.FindChildrenAsync(cancellationToken).ConfigureAwait(false); }); await Role.UpdateAsync(role, requestInfo.Session.User.ID, cancellationToken).ConfigureAwait(false); role.Set().ClearRelatedCacheAsync(oldParentID, ServiceBase.ServiceComponent.CancellationToken, requestInfo.CorrelationID).Run(); // update users var beAddedUserIDs = (role.UserIDs ?? new List <string>()).Except(oldUserIDs).ToList(); var parentRole = role.ParentRole; while (parentRole != null) { beAddedUserIDs = beAddedUserIDs.Concat(parentRole.UserIDs ?? new List <string>()).ToList(); parentRole = parentRole.ParentRole; } beAddedUserIDs = beAddedUserIDs.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); var beRemovedUserIDs = oldUserIDs.Except(role.UserIDs ?? new List <string>()).ToList(); if (!string.IsNullOrWhiteSpace(oldParentID) && !oldParentID.IsEquals(role.ParentID)) { parentRole = await oldParentID.GetRoleByIDAsync(cancellationToken).ConfigureAwait(false); while (parentRole != null) { beRemovedUserIDs = beRemovedUserIDs.Concat(parentRole.UserIDs ?? new List <string>()).ToList(); parentRole = parentRole.ParentRole; } } beRemovedUserIDs = beRemovedUserIDs.Distinct(StringComparer.OrdinalIgnoreCase).Except(beAddedUserIDs).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) }; requestUser.Extra.Clear(); requestUser.Extra["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); requestUser.Extra.Clear(); requestUser.Extra["AddedRoles"] = new[] { role.ID }.ToJArray().ToString(Formatting.None).Encrypt(Utility.EncryptionKey); await beAddedUserIDs.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 && !role.ParentID.IsEquals(oldParentID)) { await role.ParentRole.FindChildrenAsync(cancellationToken).ConfigureAwait(false); role.ParentRole._childrenIDs.Add(role.ID); await role.ParentRole.SetAsync(true, cancellationToken).ConfigureAwait(false); var json = role.ParentRole.ToJson(true, false); // message to update to all connected clients 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 }); } // update old parent if (!string.IsNullOrWhiteSpace(oldParentID) && !oldParentID.IsEquals(role.ParentID)) { parentRole = await oldParentID.GetRoleByIDAsync(cancellationToken).ConfigureAwait(false); if (parentRole != null) { await parentRole.FindChildrenAsync(cancellationToken).ConfigureAwait(false); parentRole._childrenIDs.Remove(role.ID); await parentRole.SetAsync(true, cancellationToken).ConfigureAwait(false); var json = parentRole.ToJson(true, false); // message to update to all connected clients 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(true, false); if (string.IsNullOrWhiteSpace(oldParentID) && role.ParentRole == null) { updateMessages.Add(new UpdateMessage { Type = $"{requestInfo.ServiceName}#{objectName}#Update", Data = response, DeviceID = "*" }); } // message to update to all service instances (on all other nodes) communicateMessages.Add(new CommunicateMessage(requestInfo.ServiceName) { Type = $"{objectName}#Update", 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("Update", role.Organization.Notifications, ApprovalStatus.Published, ApprovalStatus.Published, requestInfo, ServiceBase.ServiceComponent.CancellationToken).Run(); // response return(response); }
internal static async Task <Role> SetAsync(this Role role, bool updateCache = false, CancellationToken cancellationToken = default) { role?.Set(); await(updateCache && role != null && !string.IsNullOrWhiteSpace(role.ID) && !string.IsNullOrWhiteSpace(role.Title) ? Utility.Cache.SetAsync(role, cancellationToken) : Task.CompletedTask).ConfigureAwait(false); return(role); }
public static Role UpdateRoleInstance(this Role role, ExpandoObject data, string excluded = null, Action <Role> onCompleted = null) => role.Fill(data, excluded?.ToHashSet(), onCompleted);
public static Role CreateRoleInstance(this ExpandoObject data, string excluded = null, Action <Role> onCompleted = null) => Role.CreateInstance(data, excluded?.ToHashSet(), onCompleted);
internal static async Task <JObject> SearchRolesAsync(this RequestInfo requestInfo, bool isSystemAdministrator = false, CancellationToken cancellationToken = default) { // prepare var request = requestInfo.GetRequestExpando(); var query = request.Get <string>("FilterBy.Query"); var filter = request.Get <ExpandoObject>("FilterBy")?.ToFilterBy <Role>() ?? Filters <Role> .And(); if (filter is FilterBys <Role> ) { if (!string.IsNullOrWhiteSpace(query)) { var index = (filter as FilterBys <Role>).Children.FindIndex(exp => (exp as FilterBy <Role>).Attribute.IsEquals("ParentID")); if (index > -1) { (filter as FilterBys <Role>).Children.RemoveAt(index); } } else if ((filter as FilterBys <Role>).Children.FirstOrDefault(exp => (exp as FilterBy <Role>).Attribute.IsEquals("ParentID")) == null) { (filter as FilterBys <Role>).Children.Add(Filters <Role> .IsNull("ParentID")); } } var sort = string.IsNullOrWhiteSpace(query) ? request.Get <ExpandoObject>("SortBy")?.ToSortBy <Role>() ?? Sorts <Role> .Ascending("Title") : null; var pagination = request.Get <ExpandoObject>("Pagination")?.GetPagination() ?? new Tuple <long, int, int, int>(-1, 0, 20, 1); var pageSize = pagination.Item3; var pageNumber = pagination.Item4; // get organization var organizationID = filter.GetValue("SystemID") ?? requestInfo.GetParameter("SystemID") ?? requestInfo.GetParameter("x-system-id") ?? requestInfo.GetParameter("OrganizationID"); var organization = await(organizationID ?? "").GetOrganizationByIDAsync(cancellationToken).ConfigureAwait(false); if (organization == null) { throw new InformationExistedException("The organization is invalid"); } // check permission var gotRights = isSystemAdministrator || requestInfo.Session.User.IsViewer(null, null, organization, requestInfo.CorrelationID); if (!gotRights) { throw new AccessDeniedException(); } // process cache var addChildren = "true".IsEquals(requestInfo.GetHeaderParameter("x-children")); var cachedJson = string.IsNullOrWhiteSpace(query) && !addChildren ? await Utility.Cache.GetAsync <string>(Extensions.GetCacheKeyOfObjectsJson(filter, sort, pageSize, pageNumber), cancellationToken).ConfigureAwait(false) : null; if (!string.IsNullOrWhiteSpace(cachedJson)) { return(JObject.Parse(cachedJson)); } // prepare pagination var totalRecords = pagination.Item1 > -1 ? pagination.Item1 : -1; if (totalRecords < 0) { totalRecords = string.IsNullOrWhiteSpace(query) ? await Role.CountAsync(filter, Extensions.GetCacheKeyOfTotalObjects(filter, sort), cancellationToken).ConfigureAwait(false) : await Role.CountAsync(query, filter, cancellationToken).ConfigureAwait(false); } var totalPages = new Tuple <long, int>(totalRecords, pageSize).GetTotalPages(); if (totalPages > 0 && pageNumber > totalPages) { pageNumber = totalPages; } // search var objects = totalRecords > 0 ? string.IsNullOrWhiteSpace(query) ? await Role.FindAsync(filter, sort, pageSize, pageNumber, Extensions.GetCacheKey(filter, sort, pageSize, pageNumber), cancellationToken).ConfigureAwait(false) : await Role.SearchAsync(query, filter, pageSize, pageNumber, cancellationToken).ConfigureAwait(false) : new List <Role>(); // build result pagination = new Tuple <long, int, int, int>(totalRecords, totalPages, pageSize, pageNumber); if (addChildren) { await objects.Where(role => role._childrenIDs == null).ForEachAsync((role, _) => role.FindChildrenAsync(cancellationToken), cancellationToken, true, false).ConfigureAwait(false); } var response = new JObject { { "FilterBy", filter.ToClientJson(query) }, { "SortBy", sort?.ToClientJson() }, { "Pagination", pagination.GetPagination() }, { "Objects", objects.Select(role => role.ToJson(addChildren, false)).ToJArray() } }; // update cache if (string.IsNullOrWhiteSpace(query) && !addChildren) { await Utility.Cache.SetAsync(Extensions.GetCacheKeyOfObjectsJson(filter, sort, pageSize, pageNumber), response.ToString(Formatting.None), cancellationToken).ConfigureAwait(false); } // response return(response); }