Beispiel #1
0
        public async Task <List <ChannelUserVm> > GetChannelUsersAsync(long channelId, long?navigationUserId, long?requestorId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                if (navigationUserId == null)
                {
                    navigationUserId = 0;
                }

                if (requestorId != null)
                {
                    ChannelUser requestorChannelUser = await context.ChannelUsers
                                                       .FirstOrDefaultAsync(opt =>
                                                                            opt.ChannelUserRole >= ChannelUserRole.Administrator &&
                                                                            opt.ChannelId == channelId &&
                                                                            opt.UserId == requestorId)
                                                       .ConfigureAwait(false);

                    if (requestorChannelUser == null)
                    {
                        throw new PermissionDeniedException();
                    }
                }
                var channelUsers = await context.ChannelUsers
                                   .OrderByDescending(opt => opt.ChannelUserRole)
                                   .ThenBy(opt => opt.UserId)
                                   .Where(opt => opt.ChannelId == channelId && opt.UserId > navigationUserId && opt.Deleted == false)
                                   .ToListAsync()
                                   .ConfigureAwait(false);

                return(ChannelConverter.GetChannelUsers(channelUsers));
            }
        }
Beispiel #2
0
        public async Task <List <ChannelVm> > FindChannelsByStringQueryAsync(string searchQuery, long?navigationId, bool?direction = true)
        {
            ExpressionsHelper helper = new ExpressionsHelper();
            var searchExpression     = helper.GetChannelExpression(searchQuery);

            using (MessengerDbContext context = contextFactory.Create())
            {
                var query = context.Channels
                            .AsNoTracking()
                            .Where(opt => !opt.Deleted)
                            .Where(searchExpression);
                if (direction.GetValueOrDefault())
                {
                    query = query.OrderBy(opt => opt.ChannelId)
                            .Where(opt => opt.ChannelId > navigationId.GetValueOrDefault());
                }
                else
                {
                    query = query.OrderByDescending(opt => opt.ChannelId)
                            .Where(opt => opt.ChannelId < navigationId.GetValueOrDefault());
                }
                var channels = await query.ToListAsync().ConfigureAwait(false);

                return(ChannelConverter.GetChannels(channels));
            }
        }
        public async Task <ChannelVm> EditChannelAsync(ChannelVm channel, long editorUserId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                ChannelUser channelUser = await context.ChannelUsers
                                          .Include(opt => opt.Channel)
                                          .FirstOrDefaultAsync(opt =>
                                                               opt.ChannelId == channel.ChannelId &&
                                                               opt.UserId == editorUserId &&
                                                               opt.ChannelUserRole >= ChannelUserRole.Administrator)
                                          .ConfigureAwait(false);

                if (channelUser != null)
                {
                    if (channelUser.ChannelUserRole == ChannelUserRole.Administrator && (channelUser.Banned || channelUser.Deleted))
                    {
                        throw new PermissionDeniedException();
                    }

                    channelUser.Channel = ChannelConverter.GetChannel(channelUser.Channel, channel);
                    context.Update(channelUser.Channel);
                    await context.SaveChangesAsync().ConfigureAwait(false);

                    var editedChannel = ChannelConverter.GetChannel(channelUser.Channel);
                    editedChannel.UserRole         = channelUser.ChannelUserRole;
                    editedChannel.SubscribersCount = await context.ChannelUsers.CountAsync(opt => opt.Deleted == false && opt.ChannelId == channel.ChannelId).ConfigureAwait(false);

                    return(editedChannel);
                }
                throw new PermissionDeniedException();
            }
        }
        private async Task HandleChannelBlockSegmentAsync(BlockSegmentVm segment)
        {
            using (MessengerDbContext _context = CreateContext())
            {
                using (var transaction = await _context.Database.BeginTransactionAsync().ConfigureAwait(false))
                {
                    try
                    {
                        ChannelBlockData blockData = (ChannelBlockData)segment.PublicData;
                        var channel = await _context.Channels.FirstOrDefaultAsync(opt => opt.ChannelId == blockData.Channel.ChannelId).ConfigureAwait(false);

                        if (channel == null)
                        {
                            channel = ChannelConverter.GetChannel(blockData.Channel);
                            await _context.Channels.AddAsync(channel).ConfigureAwait(false);
                        }
                        else
                        {
                            channel = ChannelConverter.GetChannel(channel, blockData.Channel);
                            _context.Channels.Update(channel);
                        }
                        await _context.SaveChangesAsync().ConfigureAwait(false);

                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        AddErrorMessage(nameof(HandleChannelBlockSegmentAsync), ex.ToString());
                        transaction.Rollback();
                    }
                }
            }
        }
        public async Task CreateOrEditChannel()
        {
            var editableChannel = fillTestDbHelper.Channels.FirstOrDefault();
            var validUser       = editableChannel.ChannelUsers.FirstOrDefault(channelUser => channelUser.ChannelUserRole >= ChannelUserRole.Administrator);
            var invalidUser     = editableChannel.ChannelUsers.FirstOrDefault(channelUser => channelUser.ChannelUserRole == ChannelUserRole.Subscriber);

            editableChannel.ChannelName = "Edited channel name";
            var actualChannel = await createChannelsService.CreateOrEditChannelAsync(ChannelConverter.GetChannel(editableChannel), validUser.UserId, null);

            Assert.True(editableChannel.ChannelName == actualChannel.ChannelName);
            await Assert.ThrowsAsync <PermissionDeniedException>(async() =>
                                                                 await createChannelsService.CreateOrEditChannelAsync(ChannelConverter.GetChannel(editableChannel), invalidUser.UserId, null));

            var users              = fillTestDbHelper.Users.Skip(1);
            var creator            = fillTestDbHelper.Users.FirstOrDefault();
            var newExpectedChannel = new ChannelVm
            {
                About        = RandomExtensions.NextString(10),
                ChannelName  = "Created channel",
                ChannelUsers = users.Select(user => new ChannelUserVm
                {
                    UserId          = user.Id,
                    ChannelUserRole = ChannelUserRole.Subscriber
                }).ToList()
            };
            var newActualChannel = await createChannelsService.CreateOrEditChannelAsync(newExpectedChannel, creator.Id, newExpectedChannel.ChannelUsers);

            Assert.True(newExpectedChannel.ChannelUsers.Count() + 1 == newActualChannel.ChannelUsers.Count());
        }
        public async Task <List <ChannelDto> > CreateChannelsAsync(List <ChannelDto> channels)
        {
            if (channels == null || !channels.Any())
            {
                return(channels);
            }

            var channelsCondition = PredicateBuilder.New <Channel>();
            var resultChannels    = new List <Channel>();

            channelsCondition = channels.Aggregate(channelsCondition,
                                                   (current, value) => current.Or(opt => opt.ChannelId == value.ChannelId).Expand());
            using (MessengerDbContext context = contextFactory.Create())
            {
                var existingChannels = await context.Channels.Where(channelsCondition).ToListAsync().ConfigureAwait(false);

                var nonExistingChannels = channels.Where(channel => !existingChannels.Any(exChannel => exChannel.ChannelId == channel.ChannelId));
                resultChannels.AddRange(existingChannels);
                if (nonExistingChannels != null)
                {
                    var newChannels = ChannelConverter.GetChannels(nonExistingChannels.ToList());
                    await context.Channels.AddRangeAsync(newChannels).ConfigureAwait(false);

                    resultChannels.AddRange(newChannels);
                    await context.SaveChangesAsync().ConfigureAwait(false);
                }
                return(ChannelConverter.GetChannelsDto(resultChannels));
            }
        }
        public async Task <List <ChannelDto> > CreateOrUpdateUserChannelsAsync(List <ChannelDto> channels)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var channelsCondition = PredicateBuilder.New <Channel>();
                channelsCondition = channels.Aggregate(channelsCondition,
                                                       (current, value) => current.Or(opt => opt.ChannelId == value.ChannelId).Expand());
                List <Channel> existingChannels = await context.Channels
                                                  .Include(opt => opt.ChannelUsers)
                                                  .Where(channelsCondition)
                                                  .ToListAsync()
                                                  .ConfigureAwait(false);

                for (int i = 0; i < existingChannels.Count; i++)
                {
                    ChannelDto editedChannel = channels.FirstOrDefault(opt => opt.ChannelId == existingChannels[i].ChannelId);
                    existingChannels[i] = ChannelConverter.GetChannel(existingChannels[i], editedChannel);
                    if (!editedChannel.ChannelUsers.IsNullOrEmpty())
                    {
                        existingChannels[i].ChannelUsers = ChannelConverter.GetChannelUsers(editedChannel.ChannelUsers).ToList();
                    }
                }
                context.UpdateRange(existingChannels);
                List <ChannelDto> nonExistingChannels = channels.Where(channelDto => !existingChannels.Any(channel => channelDto.ChannelId == channel.ChannelId))?.ToList();
                List <Channel>    newChannels         = ChannelConverter.GetChannels(nonExistingChannels);
                await context.AddRangeAsync(newChannels).ConfigureAwait(false);

                await context.SaveChangesAsync().ConfigureAwait(false);

                return(ChannelConverter.GetChannelsDto(newChannels.Concat(existingChannels)));
            }
        }
Beispiel #8
0
        public async Task <List <ChannelVm> > GetChannelsAsync(IEnumerable <long> channelsId, long userId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var channelsCondition = PredicateBuilder.New <Channel>();
                channelsCondition = channelsId.Aggregate(channelsCondition,
                                                         (current, value) => current.Or(opt => opt.ChannelId == value).Expand());

                List <Channel> channels = await context.Channels
                                          .AsNoTracking()
                                          .Where(channelsCondition)
                                          .Where(opt => opt.Deleted == false)
                                          .ToListAsync()
                                          .ConfigureAwait(false);

                if (channels == null || !channels.Any())
                {
                    throw new GetConversationsException();
                }
                List <ChannelVm> resultChannels = ChannelConverter.GetChannels(channels).ToList();
                var channelUsersCondition       = PredicateBuilder.New <ChannelUser>();
                channelUsersCondition = channels.Aggregate(channelUsersCondition,
                                                           (current, value) => current.Or(opt => opt.ChannelId == value.ChannelId && opt.UserId == userId).Expand());
                List <ChannelUser> channelUsers = await context
                                                  .ChannelUsers
                                                  .AsNoTracking()
                                                  .Where(channelUsersCondition)
                                                  .ToListAsync()
                                                  .ConfigureAwait(false);

                foreach (var channel in resultChannels)
                {
                    channel.SubscribersCount = await context.ChannelUsers.CountAsync(opt =>
                                                                                     opt.Deleted == false && opt.ChannelId == channel.ChannelId).ConfigureAwait(false);

                    var currentChannelUser = channelUsers.FirstOrDefault(opt => opt.ChannelId == channel.ChannelId);
                    if (currentChannelUser != null && !currentChannelUser.Deleted)
                    {
                        channel.UserRole = currentChannelUser.ChannelUserRole;
                    }
                }
                var bannedUsers = channelUsers.Where(opt => opt.Banned)?.ToList();
                if (bannedUsers != null)
                {
                    foreach (var channelUser in bannedUsers)
                    {
                        var channel = resultChannels.FirstOrDefault(opt => opt.ChannelId == channelUser.ChannelId);
                        if (channelUser.Banned && channel != null)
                        {
                            resultChannels.Remove(channel);
                        }
                    }
                }
                return(resultChannels);
            }
        }
Beispiel #9
0
        public async Task <ChannelVm> GetChannelByIdAsync(long channelId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                Channel channel = await context.Channels
                                  .FirstOrDefaultAsync(opt => opt.ChannelId == channelId).ConfigureAwait(false);

                return(ChannelConverter.GetChannel(channel));
            }
        }
        public void Add([NotNull] IChannel source)
        {
            var converter = new ChannelConverter(source);

            lock (_channels)
                lock (_mixerInput)
                {
                    _channels.Add(source, converter);
                    _mixerInput.AddMixerInput(converter);
                }
        }
        public async Task <ChannelVm> CreateChannelAsync(ChannelVm channel, long creatorId, IEnumerable <ChannelUserVm> subscribers)
        {
            ChannelUser channelUser = new ChannelUser
            {
                ChannelUserRole = ChannelUserRole.Creator,
                SubscribedTime  = DateTime.UtcNow.ToUnixTime(),
                UserId          = creatorId,
                Deleted         = false
            };

            if (subscribers != null && await loadUsersService.IsUserBlacklisted(creatorId, subscribers.Select(opt => opt.UserId)).ConfigureAwait(false))
            {
                throw new UserBlockedException();
            }

            List <ChannelUser> channelUsers = new List <ChannelUser>()
            {
                channelUser
            };

            if (subscribers != null)
            {
                channelUsers.AddRange(ChannelConverter.GetChannelUsers(subscribers.Where(opt => opt.UserId != creatorId)));
            }
            List <UserVm> users = await loadUsersService.GetUsersByIdAsync(channelUsers.Select(opt => opt.UserId)).ConfigureAwait(false);

            if (users.Count() < channelUsers.Count())
            {
                throw new UserNotFoundException();
            }
            Channel newChannel = new Channel
            {
                ChannelId    = channel.ChannelId.GetValueOrDefault(await poolsService.GetChannelIdAsync().ConfigureAwait(false)),
                About        = channel.About,
                Deleted      = false,
                ChannelName  = channel.ChannelName,
                CreationTime = DateTime.UtcNow.ToUnixTime(),
                Photo        = channel.Photo,
                Tag          = string.IsNullOrWhiteSpace(channel.Tag) ? RandomExtensions.NextString(10, "QWERTYUIOPASDFGHJKLZXCVBNM1234567890") : channel.Tag,
                NodesId      = users.Select(opt => opt.NodeId.GetValueOrDefault()).Distinct().ToArray()
            };

            using (MessengerDbContext context = contextFactory.Create())
            {
                newChannel.ChannelUsers = channelUsers;
                var entityEntry = await context.Channels.AddAsync(newChannel).ConfigureAwait(false);

                await context.SaveChangesAsync().ConfigureAwait(false);

                var createdChannel = ChannelConverter.GetChannel(entityEntry.Entity);
                createdChannel.SubscribersCount = newChannel.ChannelUsers.Count();
                return(createdChannel);
            }
        }
Beispiel #12
0
        public async Task EditChannel()
        {
            var channel         = fillTestDbHelper.Channels.FirstOrDefault();
            var expectedChannel = ChannelConverter.GetChannelVm(ChannelConverter.GetChannelDto(channel));

            expectedChannel.ChannelName = "Edited channel name";
            expectedChannel.About       = "Edited channel about";
            expectedChannel.Tag         = "EDITEDTAG";
            var actualChannel = await updateChannelsService.EditChannelAsync(expectedChannel, channel.ChannelUsers.FirstOrDefault(opt => opt.ChannelUserRole >= ChannelUserRole.Administrator).UserId);

            Assert.True(expectedChannel.ChannelName == actualChannel.ChannelName && expectedChannel.About == actualChannel.About && expectedChannel.Tag != actualChannel.Tag);
        }
Beispiel #13
0
        public async Task <List <ChannelUserVm> > GetAdministrationChannelUsersAsync(long channelId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var channelUsers = await context.ChannelUsers.Where(opt =>
                                                                    opt.ChannelId == channelId &&
                                                                    opt.Banned == false &&
                                                                    opt.Deleted == false &&
                                                                    opt.ChannelUserRole >= ChannelUserRole.Administrator)
                                   .ToListAsync()
                                   .ConfigureAwait(false);

                return(ChannelConverter.GetChannelUsers(channelUsers));
            }
        }
        private async Task HandleChannelUsersBlockSegmentAsync(BlockSegmentVm segment)
        {
            using (MessengerDbContext _context = CreateContext())
            {
                using (var transaction = await _context.Database.BeginTransactionAsync().ConfigureAwait(false))
                {
                    try
                    {
                        if (TryDecryptPrivateData <ChannelUsersBlockData>(segment, out var blockData))
                        {
                            var channelUserCondition = PredicateBuilder.New <ChannelUser>();
                            channelUserCondition = blockData.ChannelUsers.Aggregate(channelUserCondition,
                                                                                    (current, value) => current.Or(opt => opt.ChannelId == value.ChannelId && opt.UserId == value.UserId).Expand());
                            var existingChannelUsers = await _context.ChannelUsers.Where(channelUserCondition).ToListAsync().ConfigureAwait(false);

                            if (existingChannelUsers.Any())
                            {
                                foreach (var channelUser in existingChannelUsers)
                                {
                                    var editedChannelUser = blockData.ChannelUsers.FirstOrDefault(opt => opt.UserId == channelUser.UserId);
                                    if (editedChannelUser != null)
                                    {
                                        channelUser.Banned          = editedChannelUser.Banned ?? channelUser.Banned;
                                        channelUser.Deleted         = editedChannelUser.Deleted ?? channelUser.Deleted;
                                        channelUser.ChannelUserRole = editedChannelUser.ChannelUserRole ?? channelUser.ChannelUserRole;
                                    }
                                }
                                _context.ChannelUsers.UpdateRange(existingChannelUsers);
                            }
                            var nonExistingChannelUsers = blockData.ChannelUsers.Where(channelUser => !existingChannelUsers.Any(opt => opt.UserId == channelUser.UserId));
                            if (nonExistingChannelUsers.Any())
                            {
                                var newChannelUsers = ChannelConverter.GetChannelUsers(nonExistingChannelUsers);
                                await _context.ChannelUsers.AddRangeAsync(newChannelUsers).ConfigureAwait(false);
                            }
                            await _context.SaveChangesAsync().ConfigureAwait(false);

                            transaction.Commit();
                        }
                    }
                    catch (Exception ex)
                    {
                        AddErrorMessage(nameof(HandleChannelUsersBlockSegmentAsync), ex.ToString());
                        transaction.Rollback();
                    }
                }
            }
        }
Beispiel #15
0
        public async Task <List <ChannelDto> > GetChannelsWithSubscribersAsync(IEnumerable <long> channelsId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var channelsCondition = PredicateBuilder.New <Channel>();
                channelsCondition = channelsId.Aggregate(channelsCondition,
                                                         (current, value) => current.Or(opt => opt.ChannelId == value).Expand());
                List <Channel> channels = await context.Channels
                                          .Include(opt => opt.ChannelUsers)
                                          .Where(channelsCondition)
                                          .ToListAsync()
                                          .ConfigureAwait(false);

                return(ChannelConverter.GetChannelsDto(channels));
            }
        }
        public async Task CreateOrEditChannelUsers()
        {
            var channel = fillTestDbHelper.Channels.FirstOrDefault();
            var expectedChannelUsers = ChannelConverter.GetChannelUsers(channel.ChannelUsers);
            var validUser            = channel.ChannelUsers.FirstOrDefault(opt => opt.ChannelUserRole >= ChannelUserRole.Administrator);
            var invalidUser          = channel.ChannelUsers.FirstOrDefault(opt => opt.ChannelUserRole == ChannelUserRole.Subscriber);

            foreach (var channelUser in expectedChannelUsers)
            {
                if (channelUser.UserId != validUser.UserId)
                {
                    channelUser.Deleted = true;
                }
            }
            var actualChannelUsers = await createChannelsService.CreateOrEditChannelUsersAsync(expectedChannelUsers, validUser.UserId);

            Assert.True(actualChannelUsers.All(opt => (opt.Deleted == true && opt.UserId != validUser.UserId) || opt.UserId == validUser.UserId));
            await Assert.ThrowsAsync <PermissionDeniedException>(async() =>
                                                                 await createChannelsService.CreateOrEditChannelUsersAsync(expectedChannelUsers, invalidUser.UserId));
        }
Beispiel #17
0
        public async Task <List <ChannelDto> > GetUserChannelsAsync(long userId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var query = from channel in context.Channels
                            join channelUser in context.ChannelUsers on channel.ChannelId equals channelUser.ChannelId
                            where channelUser.UserId == userId &&
                            !channelUser.Banned &&
                            !channelUser.Deleted &&
                            !channel.Deleted
                            select channel;
                List <Channel> channels = await query.AsNoTracking()
                                          .Include(opt => opt.ChannelUsers)
                                          .Include(opt => opt.Messages)
                                          .ThenInclude(opt => opt.Attachments)
                                          .ToListAsync()
                                          .ConfigureAwait(false);

                return(ChannelConverter.GetChannelsDto(channels));
            }
        }
        public async Task <List <ChannelUserVm> > CreateOrEditChannelUsersAsync(List <ChannelUserVm> channelUsers, long requestorId)
        {
            try
            {
                using (MessengerDbContext context = contextFactory.Create())
                {
                    var channelUsersCondition = PredicateBuilder.New <ChannelUser>();
                    channelUsersCondition = channelUsers.Aggregate(channelUsersCondition,
                                                                   (current, value) => current.Or(opt => opt.ChannelId == value.ChannelId && opt.UserId == value.UserId).Expand());
                    List <ChannelUserVm> result = new List <ChannelUserVm>();
                    var existingChannelsUsers   = ChannelConverter.GetChannelUsers(await context.ChannelUsers.Where(channelUsersCondition).ToListAsync().ConfigureAwait(false));
                    List <ChannelUserVm> nonExistingChannelUsers = new List <ChannelUserVm>();
                    if (existingChannelsUsers?.Any() ?? false)
                    {
                        var groups = existingChannelsUsers.GroupBy(opt => opt.ChannelId);
                        foreach (var group in groups)
                        {
                            var edited = channelUsers.Where(opt => group.Any(p => p.ChannelId == opt.ChannelId && p.UserId == opt.UserId)).ToList();
                            result.AddRange(await updateChannelsService.EditChannelUsersAsync(edited, requestorId, group.Key.GetValueOrDefault()).ConfigureAwait(false));
                        }
                        nonExistingChannelUsers = channelUsers.Where(opt => !existingChannelsUsers.Any(p => p.ChannelId == opt.ChannelId && p.UserId == opt.UserId)).ToList();
                    }
                    else
                    {
                        nonExistingChannelUsers = channelUsers;
                    }
                    if (nonExistingChannelUsers?.Any() ?? false)
                    {
                        var newChannelUsers = ChannelConverter.GetChannelUsers(nonExistingChannelUsers).ToList();
                        await context.AddRangeAsync(newChannelUsers).ConfigureAwait(false);

                        result.AddRange(ChannelConverter.GetChannelUsers(newChannelUsers));
                    }
                    var channelGroups = channelUsers.GroupBy(opt => opt.ChannelId);
                    foreach (var group in channelGroups)
                    {
                        var channelsNodesIds = await context.ChannelUsers
                                               .Where(opt => opt.ChannelId == group.Key)
                                               .Include(opt => opt.User)
                                               .Select(opt => opt.User.NodeId)
                                               .ToArrayAsync()
                                               .ConfigureAwait(false);

                        var channel = await context.Channels.FindAsync(group.Key).ConfigureAwait(false);

                        channel.NodesId = channelsNodesIds.Select(id => id.GetValueOrDefault()).Distinct().ToArray();
                        context.Channels.Update(channel);
                    }
                    await context.SaveChangesAsync().ConfigureAwait(false);

                    return(result);
                }
            }
            catch (DbUpdateException ex)
            {
                if (ex.InnerException is PostgresException postgresException)
                {
                    if (postgresException.ConstraintName == "FK_ChannelUsers_Channels_ChannelId")
                    {
                        throw new ConversationNotFoundException();
                    }

                    if (postgresException.ConstraintName == "FK_ChannelUsers_Users_UserId")
                    {
                        throw new UserNotFoundException();
                    }
                }
                throw new AddOrRemoveChannelUsersException();
            }
        }
        public async Task <List <ChannelUserVm> > AddUsersToChannelAsync(List <long> usersId, long channelId, long requestorId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var usersCondition = PredicateBuilder.New <ChannelUser>();
                usersCondition = usersId.Aggregate(usersCondition,
                                                   (current, value) => current.Or(opt => opt.UserId == value).Expand());
                var requestorUser = await context.ChannelUsers
                                    .FirstOrDefaultAsync(opt =>
                                                         opt.ChannelUserRole >= ChannelUserRole.Administrator &&
                                                         opt.ChannelId == channelId &&
                                                         opt.UserId == requestorId &&
                                                         opt.Channel.Deleted == false)
                                    .ConfigureAwait(false);

                if (requestorUser == null && (usersId.Count() > 1 || (usersId.Count() == 1 && usersId.ElementAt(0) != requestorId)))
                {
                    throw new AddUserToChannelException();
                }

                List <ChannelUser> existingUsers = await context.ChannelUsers
                                                   .Where(usersCondition)
                                                   .Where(opt => opt.ChannelId == channelId)
                                                   .ToListAsync()
                                                   .ConfigureAwait(false);

                List <long> nonExistingUsersId;
                if (existingUsers?.Any() ?? false)
                {
                    nonExistingUsersId = usersId.Where(id => !existingUsers.Any(opt => opt.UserId == id)).ToList();
                }
                else
                {
                    nonExistingUsersId = usersId;
                }

                List <ChannelUser> newChannelUsers = nonExistingUsersId.Select(id => new ChannelUser
                {
                    ChannelId       = channelId,
                    ChannelUserRole = ChannelUserRole.Subscriber,
                    SubscribedTime  = DateTime.UtcNow.ToUnixTime(),
                    UserId          = id
                }).ToList();
                var users = await loadUsersService.GetUsersByIdAsync(nonExistingUsersId).ConfigureAwait(false);

                Channel channel = await context.Channels.FirstOrDefaultAsync(opt => opt.ChannelId == channelId).ConfigureAwait(false);

                channel.NodesId = channel.NodesId.Concat(users.Select(opt => opt.NodeId.GetValueOrDefault())).Distinct().ToArray();
                context.Update(channel);
                var updatedUsers = new List <ChannelUser>();
                if (existingUsers != null)
                {
                    existingUsers.ForEach(channelUser =>
                    {
                        if (!channelUser.Banned && channelUser.Deleted)
                        {
                            channelUser.Deleted = false;
                            updatedUsers.Add(channelUser);
                        }
                    });
                    context.UpdateRange(existingUsers);
                }
                await context.AddRangeAsync(newChannelUsers).ConfigureAwait(false);

                await context.SaveChangesAsync().ConfigureAwait(false);

                return(ChannelConverter.GetChannelUsers(newChannelUsers.Concat(updatedUsers)));
            }
        }
        public async Task <List <ChannelUserVm> > EditChannelUsersAsync(List <ChannelUserVm> channelUsers, long editorUserId, long channelId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                ExpressionStarter <ChannelUser> channelUsersContidion = PredicateBuilder.New <ChannelUser>();
                channelUsersContidion = channelUsers.Aggregate(channelUsersContidion,
                                                               (current, value) => current.Or(opt => opt.ChannelId == value.ChannelId && opt.UserId == value.UserId));

                Channel currentChannel = await context.Channels.FirstOrDefaultAsync(opt => opt.ChannelId == channelId && !opt.Deleted).ConfigureAwait(false);

                if (currentChannel == null)
                {
                    throw new ObjectDoesNotExistsException("Channel not found.");
                }

                ChannelUser editorChannelUser = await context.ChannelUsers
                                                .AsNoTracking()
                                                .FirstOrDefaultAsync(opt =>
                                                                     opt.ChannelId == channelId &&
                                                                     opt.UserId == editorUserId)
                                                .ConfigureAwait(false);

                List <ChannelUser> editableChannelUsers = await context.ChannelUsers
                                                          .Where(channelUsersContidion)
                                                          .ToListAsync()
                                                          .ConfigureAwait(false);

                if (editorChannelUser == null)
                {
                    throw new PermissionDeniedException();
                }
                if (editableChannelUsers == null || editableChannelUsers.Count < channelUsers.Count())
                {
                    throw new ObjectDoesNotExistsException("Editable users are not in channel.");
                }
                if (editorChannelUser.ChannelUserRole == ChannelUserRole.Subscriber &&
                    channelUsers.Count() != 1 &&
                    channelUsers.ElementAt(0).UserId != editorChannelUser.UserId ||
                    editorChannelUser.Banned)
                {
                    throw new PermissionDeniedException();
                }
                editableChannelUsers.ForEach(channelUser =>
                {
                    ChannelUserVm edited = channelUsers.FirstOrDefault(opt => opt.UserId == channelUser.UserId);
                    if (editorChannelUser.ChannelUserRole > channelUser.ChannelUserRole)
                    {
                        channelUser.ChannelUserRole = edited.ChannelUserRole < editorChannelUser.ChannelUserRole && editorChannelUser.UserId != channelUser.UserId
                            ? edited.ChannelUserRole.GetValueOrDefault()
                            : channelUser.ChannelUserRole;
                        channelUser.Deleted = channelUser.ChannelUserRole != ChannelUserRole.Creator && edited.Deleted.GetValueOrDefault(channelUser.Deleted);
                        channelUser.Banned  = channelUser.ChannelUserRole != ChannelUserRole.Creator && edited.Banned.GetValueOrDefault(channelUser.Banned);
                    }
                    else if (editorChannelUser.UserId == channelUser.UserId)
                    {
                        channelUser.ChannelUserRole = edited.ChannelUserRole < channelUser.ChannelUserRole
                            ? edited.ChannelUserRole.GetValueOrDefault()
                            : channelUser.ChannelUserRole;
                        channelUser.Deleted = edited.Deleted.GetValueOrDefault(false);
                    }
                    else
                    {
                        throw new PermissionDeniedException();
                    }
                });
                context.ChannelUsers.UpdateRange(editableChannelUsers);
                if (channelUsers.Any(opt => opt.Deleted.GetValueOrDefault() || opt.Banned.GetValueOrDefault()))
                {
                    var query = from channel in context.Channels
                                join channelUser in context.ChannelUsers on channel.ChannelId equals channelUser.ChannelId
                                join user in context.Users on channelUser.UserId equals user.Id
                                where channel.ChannelId == channelId && !channelUser.Banned && !channelUser.Deleted
                                select user.NodeId;
                    var channelNodesId = (await query.ToListAsync().ConfigureAwait(false)).Distinct();
                    currentChannel.NodesId = channelNodesId.Select(id => id.GetValueOrDefault()).ToArray();
                    context.Channels.Update(currentChannel);
                }
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(ChannelConverter.GetChannelUsers(editableChannelUsers));
            }
        }