public async Task GetAllStatusesAsync_0Exists()
    {
        await userStatuses.AddStatusAsync(SuperUserId, 0, "here!", 1);

        var result = await userStatuses.GetUserStatusesAsync(searcher, NormalUserId, EasyFields);

        Assert.Contains(0, result.statuses.Keys);
        Assert.Contains("user", result.objects.Keys);
        Assert.Contains("content", result.objects.Keys);
        Assert.Empty(result.objects["content"]);
        var users = searcher.ToStronglyTyped <UserView>(result.objects["user"]);

        Assert.Single(users);
        Assert.Equal(SuperUserId, users.First().id);
    }
 protected Task <UserlistResult> GetUserStatusesAsync(long uid, params long[] contentIds)
 {
     using (var searcher = services.dbFactory.CreateSearch())
     {
         return(userStatuses.GetUserStatusesAsync(searcher, uid, eventQueue.GetAutoContentRequest().fields, "*", contentIds));
     }
 }
Example #3
0
    /// <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
        });
    }