async Task <PagedResult <UserWithRoles> > IUserService.GetUsersWithRoles(GetUsersQuery query)
        {
            Check.NotNull(query, name: "Query");

            var currentPrincipal = await currentUserResolver.ResolveCurrentClaimsPrincipalAsync();

            await authorizationService.AuthorizeResourceType(currentPrincipal, Operation.Read, typeof(UserWithRoles));

            var users = userRepository.GetUsers();

            if (query.ExcludeMe)
            {
                var currentUser = await currentUserResolver.ResolveAsync();

                users = users.Where(u => u.Id != currentUser.Id);
            }

            var pagedResult = new PagedResult <UserWithRoles>();

            if (!string.IsNullOrWhiteSpace(query.QueryString))
            {
                try
                {
                    var parseResult = await queryParser.ApplyQuery(users, query.QueryString);

                    pagedResult.TotalCount = parseResult.TotalCount;
                    users = parseResult.Results;
                }
                catch (Exception ex)
                {
                    throw new ValidationException("Invalid query string", ex);
                }
            }

            if (string.IsNullOrWhiteSpace(query.OrderBy))
            {
                users = users.OrderBy(u => u.Name);
            }

            if (query.Top > Constants.MaxPageSize)
            {
                users = users.Take(Constants.MaxPageSize);
            }

            var usersWithRoles = new List <UserWithRoles>();

            foreach (var user in users)
            {
                usersWithRoles.Add(new UserWithRoles(user)
                {
                    Roles = await userManager.GetRoles(user.Id)
                });
            }

            pagedResult.Results = usersWithRoles.ToArray();
            return(pagedResult);
        }
        async Task <TimeEntrySummaryReportItem[]> ITimeEntryService.GenerateSummaryReport(GenerateTimeEntrySummaryReportQuery query)
        {
            var operation        = query.IncludeTimeEntriesOfAllUsers ? Operation.ReadAll : Operation.Read;
            var currentPrincipal = await currentUserResolver.ResolveCurrentClaimsPrincipalAsync();

            await authorizationService.AuthorizeResourceType(currentPrincipal, operation, typeof(TimeEntry));

            Check.NotNull(query, "Query can not be null.");
            await validationService.Validate(query);

            var timeEntries = timeEntryRepository.GetTimeEntries();

            if (!query.IncludeTimeEntriesOfAllUsers)
            {
                var currentUser = await currentUserResolver.ResolveAsync();

                timeEntries = timeEntries.Where(te => te.OwnerId == currentUser.Id);
            }

            if (!string.IsNullOrWhiteSpace(query.QueryString))
            {
                try
                {
                    var parseResult = await queryParser.ApplyQuery(timeEntries, query.QueryString);

                    timeEntries = parseResult.Results;
                }
                catch (Exception ex)
                {
                    throw new ValidationException("Invalid query string.", ex);
                }
            }
            timeEntries = timeEntries
                          .OrderBy(te => te.OwnerId)
                          .ThenBy(te => te.Date);

            var resultIndex = new Dictionary <string, List <TimeEntry> >();

            foreach (var entry in timeEntries)
            {
                var serializedIndex = SerializeIndex(entry.OwnerId, entry.Date);
                if (!resultIndex.ContainsKey(serializedIndex))
                {
                    resultIndex.Add(serializedIndex, new List <TimeEntry>());
                }

                resultIndex[serializedIndex].Add(entry);
            }

            return(resultIndex.Values.Select(r =>
            {
                var firstTimeEntry = r.First();

                var reportItem = new TimeEntrySummaryReportItem()
                {
                    OwnerId = firstTimeEntry.OwnerId,
                    OwnerName = firstTimeEntry.Owner.Name,
                    Date = firstTimeEntry.Date.Date,
                    Notes = r.Select(te => te.Note).ToArray(),
                    TotalTime = r.Sum(te => te.Duration)
                };
                reportItem.IsUnderPreferredWorkingHoursPerDay =
                    firstTimeEntry.Owner.PreferredWorkingHourPerDay > reportItem.TotalTime;

                return reportItem;
            })
                   .ToArray());
        }