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));
            }
        }
        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)));
            }
        }
        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 #4
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();
                    }
                }
            }
        }
        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));
        }
        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> > 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));
            }
        }
        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)));
            }
        }