//This search is a plain search, no permission limits or user lookups.
 public async Task <GenericSearchResult> SearchUnrestricted(SearchRequests requests)
 {
     return(await SearchBase(requests.Copy(), new Dictionary <string, object>(requests.values)));
 }
    //A restricted search doesn't allow you to retrieve results that the given request user can't read
    public async Task <GenericSearchResult> Search(SearchRequests requests, long requestUserId = 0)
    {
        requests = requests.Copy();

        var      globalId  = Guid.NewGuid();
        UserView requester = new UserView() //This is a default user, make SURE all the relevant fields are set!
        {
            id     = 0,
            super  = false,
            groups = new List <long>()
        };

        //Do a (hopefully) quick lookup for the request user!
        if (requestUserId > 0)
        {
            try
            {
                //This apparently throws an exception if it fails
                requester = await GetById <UserView>(RequestType.user, requestUserId);
            }
            catch (Exception ex)
            {
                logger.LogWarning($"Error while looking up requester: {ex}");
                throw new ArgumentException($"Unknown request user {requestUserId}");
            }
        }

        //Need to add requester key to parameter list!
        var globalPre       = $"_sys{globalId.ToString().Replace("-", "")}";
        var requesterKey    = $"{globalPre}_requester";
        var groupsKey       = $"{globalPre}_groups";
        var parameterValues = new Dictionary <string, object>(requests.values);

        parameterValues.Add(requesterKey, requestUserId);
        parameterValues.Add(groupsKey, permissionService.GetPermissionIdsForUser(requester));

        //Modify the queries before giving them out to the query builder! We NEED them
        //to be absolutely restricted by permissions!
        foreach (var request in requests.requests)
        {
            //This USED to be part of the single search thing, but I want unrestricted search to be
            //truly unrestricted
            request.limit = Math.Min(request.limit > 0 ? request.limit : int.MaxValue, config.MaxIndividualResultSet);

            //This is VERY important: limit content searches based on permissions!
            if (request.type == RequestType.content.ToString()) //queryBuilder.ContentRequestTypes.Select(x => x.ToString()).Contains(request.type))
            {
                request.query = queryBuilder.CombineQueryClause(request.query, $"!permissionlimit(@{groupsKey}, id, R)");
            }
            if (request.type == RequestType.message.ToString() || request.type == RequestType.activity.ToString() ||
                request.type == RequestType.watch.ToString() || request.type == RequestType.vote.ToString() ||
                request.type == RequestType.message_aggregate.ToString() || request.type == RequestType.activity_aggregate.ToString())
            {
                request.query = queryBuilder.CombineQueryClause(request.query, $"!permissionlimit(@{groupsKey}, contentId, R)");
            }
            if (request.type == RequestType.message.ToString())
            {
                request.query = queryBuilder.CombineQueryClause(request.query, $"!receiveuserlimit(@{requesterKey})");
            }
            //Watches and variables and votes are per-user!
            if (request.type == RequestType.watch.ToString() || request.type == RequestType.uservariable.ToString() ||
                request.type == RequestType.vote.ToString())
            {
                request.query = queryBuilder.CombineQueryClause(request.query, $"userId = @{requesterKey}");
            }
            if (request.type == RequestType.adminlog.ToString())
            {
                if (!requester.super)
                {
                    throw new ForbiddenException("You must be super to access the admin logs!");
                }
            }
        }

        return(await SearchBase(requests, parameterValues));
    }