/// <summary> /// Get all statuses the given user is allowed to retrieve. /// </summary> /// <param name="uid"></param> /// <returns></returns> public static async Task <UserlistResult> GetUserStatusesAsync(this IUserStatusTracker userStatuses, IGenericSearch searcher, long uid, string contentFields = "*", string userFields = "*", params long[] contentIds) { //Always allow 0 in there FYI var allStatuses = await userStatuses.GetUserStatusesAsync(contentIds); var allIds = allStatuses.Keys.ToList(); //Search content AS THE USER so they only get the content they're allowed to get. Hopefully //there will never be an instance where there are over a thousand contents currently being watched var allSearch = await searcher.Search(new SearchRequests() { requests = new List <SearchRequest>() { new SearchRequest() { type = "content", fields = contentFields, query = "id in @ids" }, new SearchRequest() { type = "user", fields = userFields, query = "id in @content.createUserId or id in @userIds" } }, values = new Dictionary <string, object>() { { "ids", allIds }, { "userIds", allStatuses.SelectMany(x => x.Value.Keys) } } }, uid); //Remove the statuses they can't see, meaning anything that's NOT in the allSearch set foreach (var id in allIds.Where(x => x != 0).Except(allSearch.objects["content"].Select(x => (long)x["id"]))) { allStatuses.Remove(id); } //Don't leak information: remove users that aren't referenced var allUsers = allStatuses.SelectMany(x => x.Value.Keys).Union(allSearch.objects["content"].Select(x => (long)x["createUserId"])); allSearch.objects["user"] = allSearch.objects["user"].Where(x => allUsers.Contains((long)x["id"])); return(new UserlistResult() { statuses = allStatuses, objects = allSearch.objects }); }
public static async Task <List <T> > SearchSingleType <T>(this IGenericSearch search, long uid, SearchRequest request, Dictionary <string, object>?values = null) { //Now go get some random-ass module message var searchResult = await search.Search(new SearchRequests() { values = values ?? new Dictionary <string, object>(), requests = new List <SearchRequest> { request } }, uid); return(search.ToStronglyTyped <T>(searchResult.objects.First().Value)); }
public async void SearchAsync_InMultiList() { //Write two comments with two users in them. See if chaining to that field works var comment1 = GetNewCommentView(AllAccessContentId); comment1.text = $"And it's %{NormalUserId}%"; var comment2 = GetNewCommentView(AllAccessContentId); comment2.text = $"And it's also %{SuperUserId}%"; var writtenComment1 = await writer.WriteAsync(comment1, NormalUserId); var writtenComment2 = await writer.WriteAsync(comment2, SuperUserId); //Now search specifically for those two comments, but with users chained to the uidsInText field var search = new SearchRequests() { requests = new List <SearchRequest> { new SearchRequest() { type = "message", fields = "*", query = "id in @ids" }, new SearchRequest() { type = "user", fields = "*", query = "id in @message.uidsInText" } }, values = new Dictionary <string, object> { { "ids", new[] { writtenComment1.id, writtenComment2.id } } } }; var results = await searcher.Search(search, NormalUserId); var comments = searcher.ToStronglyTyped <MessageView>(results.objects["message"]); var users = searcher.ToStronglyTyped <UserView>(results.objects["user"]); Assert.Equal(2, comments.Count); Assert.Equal(2, users.Count); Assert.Contains(writtenComment1.id, comments.Select(x => x.id)); Assert.Contains(writtenComment2.id, comments.Select(x => x.id)); Assert.Contains(NormalUserId, users.Select(x => x.id)); Assert.Contains(SuperUserId, users.Select(x => x.id)); }
/// <summary> /// Filters the <paramref name="query"/> results using a cached request object to obtain the search parameters. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="query"></param> /// <param name="search"></param> /// <returns></returns> public static IQueryable <T> Search <T>(this IQueryable <T> query, IGenericSearch search) { return(search.Search(query)); }
/// <summary> /// Filters the <paramref name="query"/> results using the provided request object to obtain the search parameters. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="query"></param> /// <param name="search"></param> /// <param name="request"></param> /// <returns></returns> public static IQueryable <T> Search <T>(this IQueryable <T> query, IGenericSearch search, object request) { return(search.Search(query, request)); }