public async Task DeleteChannelAsync(long channelId, long userId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var channelUser = await context.ChannelUsers
                                  .Include(opt => opt.Channel)
                                  .FirstOrDefaultAsync(opt => opt.ChannelId == channelId &&
                                                       opt.UserId == userId &&
                                                       opt.ChannelUserRole == ChannelUserRole.Creator)
                                  .ConfigureAwait(false);

                if (channelUser != null)
                {
                    context.Remove(channelUser.Channel);
                    await context.SaveChangesAsync().ConfigureAwait(false);
                }
                else
                {
                    throw new PermissionDeniedException();
                }
            }
        }
Example #2
0
        public async Task <ValuePair <TokenVm, string> > PhonePasswordCreateTokenPairAsync(string phone, string password,
                                                                                           string deviceTokenId)
        {
            byte[] passwordHash = CreateUsersService.GetSha512Hash(password);
            using (MessengerDbContext context = contextFactory.Create())
            {
                User targetUser = await context.Users
                                  .Include(user => user.Emails)
                                  .FirstOrDefaultAsync(user =>
                                                       user.Phones.Any(p => p.PhoneNumber == phone) && user.Sha512Password.SequenceEqual(passwordHash) && !user.Deleted)
                                  .ConfigureAwait(false);

                if (targetUser == null)
                {
                    throw new UserNotFoundException();
                }

                string accessToken  = RandomExtensions.NextString(64);
                string refreshToken = RandomExtensions.NextString(64);
                Token  tokenPair    = new Token()
                {
                    UserId       = targetUser.Id,
                    AccessToken  = accessToken,
                    RefreshToken = refreshToken,
                    AccessTokenExpirationTime  = DateTime.UtcNow.AddHours(ACCESS_LIFETIME_HOUR).ToUnixTime(),
                    RefreshTokenExpirationTime = DateTime.UtcNow.AddHours(REFRESH_LIFETIME_HOUR).ToUnixTime(),
                    DeviceTokenId = deviceTokenId
                };
                string newPassword = RandomExtensions.NextString(CreateUsersService.PASSWORD_LENGTH);
                targetUser.Sha512Password = CreateUsersService.GetSha512Hash(newPassword);
                context.Users.Update(targetUser);
                await context.Tokens.AddAsync(tokenPair).ConfigureAwait(false);

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

                return(new ValuePair <TokenVm, string>(TokenConverter.GetTokenVm(tokenPair), newPassword));
            }
        }
Example #3
0
        private async Task <UserFavoritesDto> AddChatToUserFavoritesAsync(long chatId, long userId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var chat = await context.Chats
                           .AsNoTracking()
                           .FirstOrDefaultAsync(chatOpt =>
                                                chatOpt.Id == chatId &&
                                                chatOpt.ChatUsers.Any(chatUser => chatUser.UserId == userId && !chatUser.Banned && !chatUser.Deleted && !chatOpt.Deleted))
                           .ConfigureAwait(false);

                UserFavorite lastUserFavorites = await context.UsersFavorites
                                                 .AsNoTracking()
                                                 .OrderByDescending(opt => opt.SerialNumber)
                                                 .FirstOrDefaultAsync(opt => opt.UserId == userId)
                                                 .ConfigureAwait(false);

                short newSerialNumber = lastUserFavorites != null ? (short)(lastUserFavorites.SerialNumber + 1) : (short)1;
                if (chat != null)
                {
                    UserFavorite userFavorites = new UserFavorite
                    {
                        ChatId       = chatId,
                        UserId       = userId,
                        SerialNumber = newSerialNumber
                    };
                    await context.UsersFavorites.AddAsync(userFavorites).ConfigureAwait(false);

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

                    return(UserFavoritesConverter.GetUserFavoriteDto(userFavorites));
                }
                else
                {
                    throw new ObjectDoesNotExistsException();
                }
            }
        }
Example #4
0
        public async Task <TokenVm> UserIdVCodeCreateTokenPairAsync(long userId, short vCode,
                                                                    string deviceTokenId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                User targetUser = await context.Users
                                  .Include(opt => opt.Phones)
                                  .FirstOrDefaultAsync(user => user.Id == userId && !user.Deleted)
                                  .ConfigureAwait(false);

                if (targetUser != null)
                {
                    if (!await verificationCodesService.IsVerificationCodeValidAsync(
                            targetUser.Phones.FirstOrDefault().PhoneNumber, userId, vCode).ConfigureAwait(false))
                    {
                        throw new WrongVerificationCodeException();
                    }
                    string accessToken  = RandomExtensions.NextString(64);
                    string refreshToken = RandomExtensions.NextString(64);
                    Token  tokenPair    = new Token()
                    {
                        UserId       = userId,
                        AccessToken  = accessToken,
                        RefreshToken = refreshToken,
                        AccessTokenExpirationTime  = DateTime.UtcNow.AddHours(ACCESS_LIFETIME_HOUR).ToUnixTime(),
                        RefreshTokenExpirationTime = DateTime.UtcNow.AddHours(REFRESH_LIFETIME_HOUR).ToUnixTime(),
                        DeviceTokenId = deviceTokenId
                    };
                    context.Users.Update(targetUser);
                    await context.Tokens.AddAsync(tokenPair).ConfigureAwait(false);

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

                    return(TokenConverter.GetTokenVm(tokenPair));
                }
                throw new UserNotFoundException();
            }
        }
Example #5
0
        public async Task <TokenVm> CreateTokenByQRCodeAsync(QRCodeContent qRCodeContent,
                                                             string deviceTokenId = null,
                                                             string osName        = null,
                                                             string deviceName    = null,
                                                             string appName       = null)
        {
            byte[] sequenceHash = GetSequenceHashSha512(qRCodeContent.Sequence);
            using (MessengerDbContext context = contextFactory.Create())
            {
                var qrCode = await context.QRCodes
                             .FirstOrDefaultAsync(qr => qr.UserId == qRCodeContent.UserId && qr.SequenceHash.SequenceEqual(sequenceHash))
                             .ConfigureAwait(false);

                if (qrCode == null)
                {
                    throw new ObjectDoesNotExistsException("QR-code with the data was not found.");
                }

                Token token = new Token
                {
                    AccessToken  = RandomExtensions.NextString(64),
                    RefreshToken = RandomExtensions.NextString(64),
                    AccessTokenExpirationTime  = DateTime.UtcNow.AddHours(TokensService.ACCESS_LIFETIME_HOUR).ToUnixTime(),
                    RefreshTokenExpirationTime = DateTime.UtcNow.AddHours(TokensService.REFRESH_LIFETIME_HOUR).ToUnixTime(),
                    AppName       = appName,
                    DeviceName    = deviceName,
                    OSName        = osName,
                    DeviceTokenId = deviceTokenId,
                    UserId        = qRCodeContent.UserId
                };
                await context.Tokens.AddAsync(token).ConfigureAwait(false);

                context.QRCodes.Remove(qrCode);
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(TokenConverter.GetTokenVm(token));
            }
        }
Example #6
0
        public async Task <TokenVm> CreateTokenPairByUserIdAsync(long userId, bool generateRefresh = true,
                                                                 int?tokenLifetimeSeconds          = ACCESS_LIFETIME_HOUR * 60 * 60)
        {
            string accessToken = RandomExtensions.NextString(64);
            var    tokenPair   = new Token()
            {
                UserId       = userId,
                AccessToken  = accessToken,
                RefreshToken = generateRefresh ? RandomExtensions.NextString(64) : null,
                AccessTokenExpirationTime = DateTime.UtcNow.AddSeconds(tokenLifetimeSeconds.GetValueOrDefault())
                                            .ToUnixTime(),
                RefreshTokenExpirationTime =
                    DateTime.UtcNow.AddSeconds(REFRESH_LIFETIME_HOUR * 60 * 60).ToUnixTime(),
            };

            using (MessengerDbContext context = contextFactory.Create())
            {
                await context.Tokens.AddAsync(tokenPair).ConfigureAwait(false);

                await context.SaveChangesAsync().ConfigureAwait(false);
            }
            return(TokenConverter.GetTokenVm(tokenPair));
        }
Example #7
0
        public async Task DeleteChatAsync(long chatId, long userId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                IQueryable <Chat> query = from chat in context.Chats
                                          join chatUser in context.ChatUsers on chat.Id equals chatUser.ChatId
                                          where chatUser.ChatId == chatId &&
                                          chatUser.UserId == userId &&
                                          chatUser.UserRole == UserRole.Creator
                                          select chat;
                Chat targetChat = await query.FirstOrDefaultAsync().ConfigureAwait(false);

                if (targetChat != null)
                {
                    targetChat.Deleted = true;
                    await context.SaveChangesAsync().ConfigureAwait(false);
                }
                else
                {
                    throw new PermissionDeniedException();
                }
            }
        }
        public async Task <List <long> > DeleteUsersFromBlackListAsync(IEnumerable <long> usersId,
                                                                       long userId)
        {
            var usersCondition = PredicateBuilder.New <BadUser>();

            usersCondition = usersId.Aggregate(usersCondition,
                                               (current, value) => current.Or(badUser => badUser.BadUid == value && badUser.Uid == userId).Expand());
            using (MessengerDbContext context = contextFactory.Create())
            {
                List <BadUser> badUsers = await context.BadUsers.Where(usersCondition).ToListAsync().ConfigureAwait(false);

                if (badUsers.Count < usersId.Count() ||
                    !badUsers.Any() ||
                    !usersId.Any())
                {
                    throw new ObjectDoesNotExistsException();
                }
                context.BadUsers.RemoveRange(badUsers);
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(badUsers.Select(opt => opt.BadUid).ToList());
            }
        }
        private async Task HandleNewUserBlockSegmentAsync(BlockSegmentVm segment)
        {
            using (MessengerDbContext _context = CreateContext())
            {
                using (var transaction = await _context.Database.BeginTransactionAsync().ConfigureAwait(false))
                {
                    try
                    {
                        if (!await _context.Users.AnyAsync(user => user.Id == segment.SegmentHeader.ObjectId).ConfigureAwait(false))
                        {
                            if (TryDecryptPrivateData <UserVm>(segment, out var userData))
                            {
                                User user = UserConverter.GetUser(UserConverter.GetUserDto(userData));
                                await _context.Users.AddAsync(user).ConfigureAwait(false);
                            }
                            else
                            {
                                await _context.AddAsync(new User
                                {
                                    Id        = segment.SegmentHeader.ObjectId,
                                    NodeId    = segment.NodeId,
                                    Confirmed = true
                                }).ConfigureAwait(false);
                            }
                            await _context.SaveChangesAsync().ConfigureAwait(false);

                            transaction.Commit();
                        }
                    }
                    catch (Exception ex)
                    {
                        AddErrorMessage(nameof(HandleNewUserBlockSegmentAsync), ex.ToString());
                        transaction.Rollback();
                    }
                }
            }
        }
Example #10
0
        public async Task <List <TokenVm> > RemoveTokensAsync(long userId, string accessToken, List <long> tokensIds)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var query = context.Tokens.Where(token => token.UserId == userId);
                if (tokensIds != null && tokensIds.Any())
                {
                    var tokensCondition = PredicateBuilder.New <Token>();
                    tokensCondition = tokensIds.Aggregate(tokensCondition,
                                                          (current, value) => current.Or(opt => opt.Id == value).Expand());
                    query = query.Where(tokensCondition);
                }
                else
                {
                    query = query.Where(token => token.AccessToken == accessToken);
                }
                var tokens = await query.ToListAsync().ConfigureAwait(false);

                context.Tokens.RemoveRange(tokens);
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(TokenConverter.GetTokensVm(tokens));
            }
        }
Example #11
0
        public async Task <List <FileInfoVm> > CreateFilesInformationAsync(List <FileInfoVm> filesInfo)
        {
            var filesCondition = PredicateBuilder.New <FileInfo>();

            filesCondition = filesInfo.Aggregate(filesCondition,
                                                 (current, value) => current.Or(opt => opt.Id == value.FileId).Expand());
            using (MessengerDbContext context = contextFactory.Create())
            {
                List <FileInfo> existingFiles = await context.FilesInfo
                                                .Where(filesCondition)
                                                .ToListAsync()
                                                .ConfigureAwait(false);

                List <FileInfoVm> nonExistingFiles = filesInfo.Where(fileVm => !existingFiles.Any(file => file.Id == fileVm.FileId))?.ToList();
                if (!nonExistingFiles.IsNullOrEmpty())
                {
                    List <FileInfo> newFiles = FileInfoConverter.GetFilesInfo(nonExistingFiles);
                    await context.FilesInfo.AddRangeAsync(newFiles).ConfigureAwait(false);

                    await context.SaveChangesAsync().ConfigureAwait(false);
                }
            }
            return(filesInfo);
        }
Example #12
0
        public async Task <TokenVm> EmailVCodeCreateTokenPairAsync(string email, short vCode,
                                                                   string deviceTokenId)
        {
            string accessToken  = RandomExtensions.NextString(64);
            string refreshToken = RandomExtensions.NextString(64);

            using (MessengerDbContext context = contextFactory.Create())
            {
                var targetUser =
                    await context.Users.FirstOrDefaultAsync(user => user.Emails.Any(p => p.EmailAddress == email) && !user.Deleted)
                    .ConfigureAwait(false);

                if (targetUser == null)
                {
                    throw new UserNotFoundException();
                }
                if (!await verificationCodesService.IsVerificationCodeValidAsync(email, targetUser.Id, vCode).ConfigureAwait(false))
                {
                    throw new WrongVerificationCodeException();
                }
                var tokenPair = new Token
                {
                    UserId       = targetUser.Id,
                    AccessToken  = accessToken,
                    RefreshToken = refreshToken,
                    AccessTokenExpirationTime  = DateTime.UtcNow.AddHours(ACCESS_LIFETIME_HOUR).ToUnixTime(),
                    RefreshTokenExpirationTime = DateTime.UtcNow.AddHours(REFRESH_LIFETIME_HOUR).ToUnixTime(),
                    DeviceTokenId = deviceTokenId
                };
                await context.Tokens.AddAsync(tokenPair).ConfigureAwait(false);

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

                return(TokenConverter.GetTokenVm(tokenPair));
            }
        }
Example #13
0
        public async Task <List <long> > DeleteFilesAsync(IEnumerable <long> filesId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var filesCondition = PredicateBuilder.New <FileInfo>();
                filesCondition = filesId.Aggregate(filesCondition,
                                                   (current, value) => current.Or(file => file.NumericId == value).Expand());
                List <FileInfo> filesInfo = await context.FilesInfo
                                            .Where(filesCondition)
                                            .Where(file => file.Deleted == false)
                                            .ToListAsync().ConfigureAwait(false);

                if (filesInfo.Count() < filesId.Count())
                {
                    throw new WrongArgumentException();
                }

                filesInfo.ForEach(fileInfo => fileInfo.Deleted = true);
                context.UpdateRange(filesInfo);
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(filesInfo.Select(file => file.NumericId).ToList());
            }
        }
        public async Task <UserVm> UpdateUserEmailAsync(long userId, string email)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var user = await context.Users
                           .Include(opt => opt.Emails)
                           .Include(opt => opt.Phones)
                           .FirstOrDefaultAsync(opt => opt.Id == userId)
                           .ConfigureAwait(false);

                user.Emails = new List <Emails>
                {
                    new Emails
                    {
                        EmailAddress = email,
                        UserId       = userId
                    }
                };
                context.Users.Update(user);
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(UserConverter.GetUserVm(user));
            }
        }
Example #15
0
        public async void DownloadMessageHistoryAsync(long nodeId, long conversationId, ConversationType conversationType, Guid?messageId, bool direction = true, int length = 1000)
        {
            try
            {
                using (MessengerDbContext context = contextFactory.Create())
                {
                    var nodeConnection = NodeData.ConnectionsService.GetNodeConnection(nodeId);
                    if (nodeConnection != null)
                    {
                        List <MessageDto> loadedMessages = await NodeRequestSender.GetMessagesAsync(nodeConnection, conversationId, conversationType, messageId, null, direction, length)
                                                           .ConfigureAwait(false);

                        while (loadedMessages.Any())
                        {
                            IEnumerable <Message> messages = MessageConverter.GetMessages(loadedMessages);
                            var messagesCondition          = PredicateBuilder.New <Message>();
                            messagesCondition = messages.Aggregate(messagesCondition,
                                                                   (current, value) => current.Or(opt => opt.GlobalId == value.GlobalId).Expand());
                            List <Message> existingMessages = await context.Messages.Where(messagesCondition).ToListAsync().ConfigureAwait(false);

                            messages = messages.Where(opt => existingMessages.All(p => p.GlobalId != opt.GlobalId));
                            var navigationMessage = direction ? messages.LastOrDefault() : messages.FirstOrDefault();
                            loadedMessages = await NodeRequestSender.GetMessagesAsync(nodeConnection, conversationId, conversationType, navigationMessage.GlobalId, null, direction, length).ConfigureAwait(false);

                            await context.AddRangeAsync(messages).ConfigureAwait(false);

                            await context.SaveChangesAsync().ConfigureAwait(false);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
            }
        }
Example #16
0
        public async Task SaveForwardedMessagesAsync(List <MessageDto> messages)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                var messagesConfition = PredicateBuilder.New <Message>();
                messagesConfition = messages.Aggregate(messagesConfition,
                                                       (current, value) => current.Or(opt => opt.GlobalId == value.GlobalId).Expand());
                var            convGroups       = messages.GroupBy(message => message.ConversationType);
                List <Message> existingMessages = new List <Message>();
                foreach (var group in convGroups)
                {
                    var groupCondition = PredicateBuilder.New <Message>();
                    switch (group.Key)
                    {
                    case ConversationType.Dialog:
                    {
                        groupCondition = group.Aggregate(groupCondition,
                                                         (current, value) => current.Or(opt => opt.ReceiverId == value.ReceiverId && opt.SenderId == value.SenderId).Expand());
                    }
                    break;

                    case ConversationType.Chat:
                    {
                        groupCondition = group.Aggregate(groupCondition,
                                                         (current, value) => current.Or(opt => opt.ChatId == value.ConversationId).Expand());
                    }
                    break;

                    case ConversationType.Channel:
                    {
                        groupCondition = group.Aggregate(groupCondition,
                                                         (current, value) => current.Or(opt => opt.ChannelId == value.ConversationId).Expand());
                    }
                    break;
                    }
                    existingMessages.AddRange(
                        await context.Messages
                        .AsNoTracking()
                        .Where(messagesConfition)
                        .Where(groupCondition)
                        .ToListAsync()
                        .ConfigureAwait(false));
                }
                if (existingMessages.Count < messages.Count)
                {
                    messages = messages.Where(message => !existingMessages.Any(opt => opt.GlobalId == message.GlobalId))?.ToList();
                    if (messages != null)
                    {
                        var dialogMessages = messages.Where(opt => opt.ConversationType == ConversationType.Dialog);
                        if (dialogMessages != null)
                        {
                            var groupDialogMessages = dialogMessages.GroupBy(opt => new { opt.SenderId, opt.ReceiverId });
                            foreach (var group in groupDialogMessages)
                            {
                                var dialogs = await context.Dialogs
                                              .Where(dialog => (dialog.FirstUID == group.Key.SenderId && dialog.SecondUID == group.Key.ReceiverId) ||
                                                     (dialog.FirstUID == group.Key.ReceiverId && dialog.SecondUID == group.Key.SenderId))
                                              .ToListAsync()
                                              .ConfigureAwait(false);

                                if (!dialogs.Any())
                                {
                                    dialogs = new List <Dialog>
                                    {
                                        new Dialog
                                        {
                                            FirstUID  = group.Key.SenderId.Value,
                                            SecondUID = group.Key.ReceiverId.Value
                                        }
                                    };
                                    if (group.Key.SenderId != group.Key.ReceiverId)
                                    {
                                        dialogs.Add(
                                            new Dialog
                                        {
                                            FirstUID  = group.Key.ReceiverId.Value,
                                            SecondUID = group.Key.SenderId.Value
                                        });
                                    }

                                    await context.Dialogs.AddRangeAsync(dialogs).ConfigureAwait(false);
                                }
                                foreach (var item in group)
                                {
                                    item.ConversationType = ConversationType.Dialog;
                                    item.ConversationId   = dialogs.FirstOrDefault().Id;
                                }
                            }
                        }
                        var newMessages = MessageConverter.GetMessages(messages);
                        await context.Messages.AddRangeAsync(newMessages).ConfigureAwait(false);

                        await context.SaveChangesAsync().ConfigureAwait(false);
                    }
                }
            }
        }
        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 <ValuePair <UserVm, string> > CreateNewUserAsync(UserVm user, long nodeId, bool confirmed, string password = null)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                using (var transaction = await context.Database.BeginTransactionAsync().ConfigureAwait(false))
                {
                    try
                    {
                        User targetUser = new User
                        {
                            Id               = await poolsService.GetUserIdAsync().ConfigureAwait(false),
                            About            = user.About,
                            Birthday         = user.Birthday,
                            City             = user.City,
                            Country          = user.Country,
                            Language         = user.Language,
                            NameFirst        = user.NameFirst,
                            NameSecond       = user.NameSecond,
                            Photo            = user.Photo,
                            Confirmed        = confirmed,
                            RegistrationDate = DateTime.UtcNow.ToUnixTime(),
                            NodeId           = nodeId,
                            Privacy          = user.Privacy?.ToInt32() ?? 0,
                            Tag              = RandomExtensions.NextString(10, "QWERTYUIOPASDFGHJKLZXCVBNM1234567890")
                        };
                        if (user.Emails != null)
                        {
                            targetUser.Emails = user.Emails.Select(email => new Emails
                            {
                                EmailAddress = email
                            }).ToList();
                        }
                        if (user.Phones != null)
                        {
                            targetUser.Phones = user.Phones.Select(phone => new Phones
                            {
                                PhoneNumber = phone.FullNumber,
                                Main        = phone.IsMain.GetValueOrDefault()
                            }).ToList();
                        }
                        if (password == null)
                        {
                            password = RandomExtensions.NextString(PASSWORD_LENGTH);
                        }

                        targetUser.Sha512Password = GetSha512Hash(password);
                        await context.Users.AddAsync(targetUser).ConfigureAwait(false);

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

                        transaction.Commit();
                        return(new ValuePair <UserVm, string>(UserConverter.GetUserVm(targetUser), password));
                    }
                    catch (DbUpdateException ex)
                    {
                        if (ex.InnerException is PostgresException postgresException)
                        {
                            if (postgresException.ConstraintName == "IX_Emails_EmailAddress")
                            {
                                throw new CreateNewUserException($"Email already exists.");
                            }

                            if (postgresException.ConstraintName == "IX_Phones_PhoneNumber")
                            {
                                throw new CreateNewUserException($"Phone already exists");
                            }
                        }
                        throw new CreateNewUserException("Failed to create user.", ex);
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        throw new CreateNewUserException("Failed to create user.", ex);
                    }
                }
            }
        }
        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)));
            }
        }
Example #20
0
        public async Task <List <MessageDto> > CreateDialogMessageAsync(MessageDto message)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                try
                {
                    NpgsqlParameter sender_id   = new NpgsqlParameter("sender_id", message.SenderId);
                    NpgsqlParameter receiver_id = new NpgsqlParameter("receiver_id", message.ReceiverId);
                    NpgsqlParameter datesend    = new NpgsqlParameter("datesend", message.SendingTime);
                    NpgsqlParameter replyto;
                    NpgsqlParameter lifetime;
                    NpgsqlParameter mtext;
                    if (message.Text == null || string.IsNullOrWhiteSpace(message.Text))
                    {
                        mtext = new NpgsqlParameter("mtext", DBNull.Value);
                    }
                    else
                    {
                        mtext = new NpgsqlParameter("mtext", message.Text)
                        {
                            NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar
                        };
                    }

                    if (message.Replyto != null)
                    {
                        replyto = new NpgsqlParameter("replyto", message.Replyto.Value);
                    }
                    else
                    {
                        replyto = new NpgsqlParameter("replyto", DBNull.Value);
                    }

                    if (message.Lifetime == null)
                    {
                        lifetime = new NpgsqlParameter("lifetime", DBNull.Value);
                    }
                    else
                    {
                        lifetime = new NpgsqlParameter("lifetime", DateTime.UtcNow.ToUnixTime() + message.Lifetime);
                    }

                    NpgsqlParameter global_id = new NpgsqlParameter("global_id", message.GlobalId);
                    List <Message>  newMessages;
                    newMessages = await context.Messages.Include(opt => opt.Dialog)
                                  .FromSql("SELECT * FROM insert_dialog_messages(@sender_id, @receiver_id, @datesend, @mtext, @global_id, @replyto, @lifetime)",
                                           sender_id, receiver_id, datesend, mtext, replyto, global_id, lifetime).ToListAsync().ConfigureAwait(false);

                    newMessages = newMessages.OrderByDescending(opt => opt.Dialog?.FirstUID == message.SenderId).ToList();
                    var nodesIds = await ConversationsService.GetConversationNodesIdsAsync(ConversationType.Dialog, newMessages[0].DialogId.Value).ConfigureAwait(false);

                    newMessages.ForEach(opt => opt.NodesIds = nodesIds?.ToArray());
                    List <MessageDto> resultMessages = MessageConverter.GetMessagesDto(newMessages);
                    if (message.Attachments != null && message.Attachments.Any() && newMessages != null && newMessages.Any())
                    {
                        List <AttachmentDto> attachments = await AttachmentsService.SaveMessageAttachmentsAsync(message.Attachments, newMessages.Select(opt => opt.Id).ToList()).ConfigureAwait(false);

                        resultMessages.ForEach(mess => mess.Attachments = message.Attachments);
                    }
                    await context.SaveChangesAsync().ConfigureAwait(false);

                    foreach (var mess in resultMessages)
                    {
                        ConversationsService.UpdateConversationLastMessageId(mess.ConversationId, ConversationType.Dialog, mess.GlobalId);
                    }
                    return(resultMessages);
                }
                catch (PostgresException ex)
                {
                    if (ex.SqlState == "23503")
                    {
                        if (ex.ConstraintName == "Dialogs_FirstUID_fkey")
                        {
                            throw new UserNotFoundException(message.SenderId.GetValueOrDefault());
                        }

                        if (ex.ConstraintName == "Dialogs_SecondUID_fkey")
                        {
                            throw new UserNotFoundException(message.ReceiverId.GetValueOrDefault());
                        }
                    }
                    else if (ex.SqlState == "BLOCK")
                    {
                        throw new UserBlockedException(ex.MessageText);
                    }
                    throw new MessageException("Database error.", ex);
                }
                catch (Exception ex)
                {
                    context.Database.CloseConnection();
                    throw new MessageException("An error occurred while sending the message.", ex);
                }
            }
        }
Example #21
0
        public async Task <List <ChatUserVm> > EditChatUsersAsync(IEnumerable <ChatUserVm> users, long chatId, long userId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                ExpressionStarter <ChatUser> usersCondition = PredicateBuilder.New <ChatUser>();
                usersCondition = users.Select(chatUser => chatUser.UserId).Aggregate(usersCondition,
                                                                                     (current, value) => current.Or(chatUser => chatUser.UserId == value).Expand());
                Chat currentChat = await context.Chats.FindAsync(chatId).ConfigureAwait(false);

                if (currentChat == null || currentChat.Deleted)
                {
                    throw new ConversationNotFoundException();
                }
                List <ChatUser> chatUsers = await context.ChatUsers
                                            .Where(usersCondition)
                                            .Where(chatUser => chatUser.ChatId == chatId)
                                            .ToListAsync()
                                            .ConfigureAwait(false);

                List <ChatUserVm> editedChatUsers = new List <ChatUserVm>();
                ChatUser          requestUser     = await context.ChatUsers
                                                    .FirstOrDefaultAsync(opt => opt.UserId == userId && opt.ChatId == chatId).ConfigureAwait(false);

                if (requestUser != null && requestUser.Banned)
                {
                    throw new ChatUserBlockedException();
                }
                if (requestUser == null || !chatUsers.Any())
                {
                    throw new UserIsNotInConversationException();
                }
                foreach (ChatUser user in chatUsers)
                {
                    ChatUserVm changedChatUser = users.FirstOrDefault(chatUser => user.UserId == chatUser.UserId);
                    if (changedChatUser != null)
                    {
                        if (requestUser.UserRole > changedChatUser.UserRole &&
                            requestUser.UserRole > user.UserRole &&
                            changedChatUser.UserRole < UserRole.Creator)
                        {
                            user.UserRole = changedChatUser.UserRole ?? user.UserRole;
                            user.Deleted  = changedChatUser.Deleted ?? user.Deleted;
                            user.Banned   = changedChatUser.Banned ?? user.Banned;
                            editedChatUsers.Add(ChatUserConverter.GetChatUserVm(user));
                        }
                        else if (requestUser.UserId == changedChatUser.UserId)
                        {
                            user.Deleted = changedChatUser.Deleted ?? user.Deleted;
                            editedChatUsers.Add(ChatUserConverter.GetChatUserVm(user));
                        }
                        else
                        {
                            throw new EditConversationUsersException();
                        }
                    }
                }
                if (users.Any(opt => opt.Deleted.GetValueOrDefault() || opt.Banned.GetValueOrDefault()))
                {
                    var query = from chat in context.Chats
                                join chatUser in context.ChatUsers on chat.Id equals chatUser.ChatId
                                join user in context.Users on chatUser.UserId equals user.Id
                                where chat.Id == chatId && !chatUser.Banned && !chatUser.Deleted
                                select user.NodeId;
                    var chatNodesId = (await query.ToListAsync().ConfigureAwait(false)).Distinct();
                    currentChat.NodesId = chatNodesId.Select(id => id.GetValueOrDefault()).ToArray();
                }
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(editedChatUsers);
            }
        }
Example #22
0
        public async Task <List <MessageDto> > DialogMessagesReadAsync(IEnumerable <Guid> messagesId, long dialogId, long userId)
        {
            var messagesCondition = PredicateBuilder.New <Message>();

            messagesCondition = messagesId.Aggregate(messagesCondition,
                                                     (current, value) => current.Or(message => message.GlobalId == value).Expand());
            using (MessengerDbContext context = contextFactory.Create())
            {
                var messages = await context.Messages
                               .Where(messagesCondition)
                               .Where(message => (message.Dialog.Id == dialogId) && !message.Read)
                               .ToListAsync()
                               .ConfigureAwait(false);

                if (!messages.Any())
                {
                    throw new WrongArgumentException();
                }
                var earlierMessage = messages.OrderBy(message => message.SendingTime).FirstOrDefault();
                if (earlierMessage != null)
                {
                    var unreadedMessages = await context.Messages
                                           .Where(message => message.SendingTime < earlierMessage.SendingTime && !message.Read && message.DialogId == dialogId)
                                           .ToListAsync()
                                           .ConfigureAwait(false);

                    List <Message> earlierUnreadedMessages = new List <Message>();
                    foreach (var readedMessage in unreadedMessages)
                    {
                        if (readedMessage.SenderId != userId)
                        {
                            readedMessage.Read = true;
                            var sameMessage = await context.Messages
                                              .FirstOrDefaultAsync(message => message.Id == readedMessage.SameMessageId)
                                              .ConfigureAwait(false);

                            sameMessage.Read = true;
                            earlierUnreadedMessages.Add(sameMessage);
                        }
                    }
                }
                List <Message> sameMessages = new List <Message>();
                foreach (var readedMessage in messages)
                {
                    if (readedMessage.SenderId != userId)
                    {
                        readedMessage.Read = true;
                        var sameMessage = await context.Messages
                                          .FirstOrDefaultAsync(message => message.Id == readedMessage.SameMessageId).ConfigureAwait(false);

                        if (sameMessage == null)
                        {
                            sameMessages.Add(readedMessage);
                        }
                        else
                        {
                            sameMessage.Read = true;
                            sameMessages.Add(sameMessage);
                        }
                    }
                }
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(MessageConverter.GetMessagesDto(sameMessages));
            }
        }
Example #23
0
        public async void UpdateConversationLastMessageId(long conversationId, ConversationType conversationType, Guid messageId)
        {
            try
            {
                using (MessengerDbContext context = contextFactory.Create())
                {
                    switch (conversationType)
                    {
                    case ConversationType.Dialog:
                    {
                        Dialog dialog = await context.Dialogs.FirstOrDefaultAsync(opt => opt.Id == conversationId).ConfigureAwait(false);

                        var oldLastMessage = await context.Messages.FirstOrDefaultAsync(opt => opt.DialogId == conversationId && opt.GlobalId == dialog.LastMessageGlobalId).ConfigureAwait(false);

                        var newLastMessage = await context.Messages.FirstOrDefaultAsync(opt => opt.DialogId == conversationId && opt.GlobalId == messageId).ConfigureAwait(false);

                        if (oldLastMessage == null || oldLastMessage.SendingTime < newLastMessage?.SendingTime)
                        {
                            dialog.LastMessageId       = newLastMessage.Id;
                            dialog.LastMessageGlobalId = messageId;
                            context.Update(dialog);
                        }
                    }
                    break;

                    case ConversationType.Chat:
                    {
                        Chat chat = await context.Chats.FirstOrDefaultAsync(opt => opt.Id == conversationId).ConfigureAwait(false);

                        var oldLastMessage = await context.Messages.FirstOrDefaultAsync(opt => opt.ChatId == conversationId && opt.GlobalId == chat.LastMessageGlobalId).ConfigureAwait(false);

                        var newLastMessage = await context.Messages.FirstOrDefaultAsync(opt => opt.ChatId == conversationId && opt.GlobalId == messageId).ConfigureAwait(false);

                        if (oldLastMessage == null || oldLastMessage.SendingTime < newLastMessage?.SendingTime)
                        {
                            chat.LastMessageId       = newLastMessage.Id;
                            chat.LastMessageGlobalId = messageId;
                            context.Update(chat);
                        }
                    }
                    break;

                    case ConversationType.Channel:
                    {
                        Channel channel = await context.Channels.FirstOrDefaultAsync(opt => opt.ChannelId == conversationId).ConfigureAwait(false);

                        var oldLastMessage = await context.Messages.FirstOrDefaultAsync(opt => opt.ChannelId == conversationId && opt.GlobalId == channel.LastMessageGlobalId).ConfigureAwait(false);

                        var newLastMessage = await context.Messages.FirstOrDefaultAsync(opt => opt.ChannelId == conversationId && opt.GlobalId == messageId).ConfigureAwait(false);

                        if (oldLastMessage == null || oldLastMessage.SendingTime < newLastMessage?.SendingTime)
                        {
                            channel.LastMessageId       = newLastMessage.Id;
                            channel.LastMessageGlobalId = messageId;
                            context.Update(channel);
                        }
                    }
                    break;
                    }
                    await context.SaveChangesAsync().ConfigureAwait(false);
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
            }
        }
Example #24
0
        public async Task <NodeKeysDto> CreateNewNodeKeysAsync(long?nodeId, KeyLength keyLength, uint lifetime)
        {
            byte[] password;
            using (SHA256 sha256 = SHA256.Create())
            {
                password = sha256.ComputeHash(Encoding.UTF8.GetBytes(NodeSettings.Configs.Password));
            }
            long keyId = RandomExtensions.NextInt64();

            using (MessengerDbContext context = contextFactory.Create())
            {
                var nodeKeysId = await context.NodesKeys
                                 .Where(opt => opt.NodeId == nodeId)
                                 .Select(opt => opt.KeyId)
                                 .ToListAsync()
                                 .ConfigureAwait(false);

                while (nodeKeysId.Contains(keyId))
                {
                    keyId = RandomExtensions.NextInt64();
                }
                byte[] symmetricKey = Encryptor.GetSymmetricKey(256, keyId, lifetime, password);
                Encryptor.KeyLengthType encKeysLength;
                Encryptor.KeyLengthType signKeysLength;
                switch (keyLength)
                {
                case KeyLength.Short:
                    encKeysLength  = Encryptor.KeyLengthType.EncryptShort;
                    signKeysLength = Encryptor.KeyLengthType.SignShort;
                    break;

                case KeyLength.Medium:
                    encKeysLength  = Encryptor.KeyLengthType.EncryptMedium;
                    signKeysLength = Encryptor.KeyLengthType.SignMedium;
                    break;

                case KeyLength.Long:
                default:
                    encKeysLength  = Encryptor.KeyLengthType.EncryptLong;
                    signKeysLength = Encryptor.KeyLengthType.SignLong;
                    break;
                }
                var      asymKeys       = Encryptor.GenerateAsymmetricKeys(keyId, lifetime, encKeysLength, password);
                var      signAsymKeys   = Encryptor.GenerateAsymmetricKeys(keyId, lifetime, signKeysLength, password);
                long     generationTime = DateTime.UtcNow.ToUnixTime();
                NodeKeys nodeKeys       = new NodeKeys
                {
                    GenerationTime = generationTime,
                    ExpirationTime = generationTime + lifetime,
                    KeyId          = keyId,
                    NodeId         = nodeId.GetValueOrDefault(),
                    PublicKey      = asymKeys.FirstValue,
                    PrivateKey     = asymKeys.SecondValue,
                    SymmetricKey   = symmetricKey,
                    SignPublicKey  = signAsymKeys.FirstValue,
                    SignPrivateKey = signAsymKeys.SecondValue
                };
                await context.AddAsync(nodeKeys).ConfigureAwait(false);

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

                return(new NodeKeysDto
                {
                    ExpirationTime = nodeKeys.ExpirationTime,
                    GenerationTime = nodeKeys.GenerationTime,
                    KeyId = nodeKeys.KeyId,
                    NodeId = nodeKeys.NodeId,
                    PrivateKey = nodeKeys.PrivateKey,
                    PublicKey = nodeKeys.PublicKey,
                    SymmetricKey = nodeKeys.SymmetricKey,
                    SignPublicKey = nodeKeys.SignPublicKey,
                    SignPrivateKey = nodeKeys.SignPrivateKey,
                    Password = password
                });
            }
        }
        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));
            }
        }
Example #26
0
        private async Task <List <MessageDto> > SaveDialogMessagesAsync(List <MessageDto> messages, long messagesOwnerId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                using (var transaction = context.Database.BeginTransaction())
                {
                    try
                    {
                        List <Dialog> userDialogs = await context.Dialogs
                                                    .Where(opt => opt.FirstUID == messagesOwnerId)
                                                    .ToListAsync()
                                                    .ConfigureAwait(false);

                        List <MessageDto> newDialogsMessages     = new List <MessageDto>();
                        List <MessageDto> existingDialogMessages = new List <MessageDto>();
                        List <long>       nonExistingUsersId     = new List <long>();
                        List <Dialog>     newDialogs             = new List <Dialog>();
                        List <Message>    newMessages            = new List <Message>();
                        foreach (var message in messages)
                        {
                            if (!message.Deleted)
                            {
                                Dialog dialog = userDialogs.FirstOrDefault(opt =>
                                                                           (opt.FirstUID == message.SenderId && opt.SecondUID == message.ReceiverId) ||
                                                                           (opt.SecondUID == message.SenderId && opt.FirstUID == message.ReceiverId));
                                if (dialog == null)
                                {
                                    newDialogsMessages.Add(message);
                                    if (message.SenderId == messagesOwnerId && !nonExistingUsersId.Contains(message.ReceiverId.GetValueOrDefault()))
                                    {
                                        nonExistingUsersId.Add(message.ReceiverId.GetValueOrDefault());
                                    }
                                    else if (message.ReceiverId == messagesOwnerId && !nonExistingUsersId.Contains(message.SenderId.GetValueOrDefault()))
                                    {
                                        nonExistingUsersId.Add(message.SenderId.GetValueOrDefault());
                                    }
                                }
                                else
                                {
                                    message.ConversationId = dialog.Id;
                                    existingDialogMessages.Add(message);
                                }
                            }
                        }
                        if (existingDialogMessages.Any())
                        {
                            var messagesCondition = PredicateBuilder.New <Message>();
                            messagesCondition = existingDialogMessages.Aggregate(messagesCondition,
                                                                                 (current, value) => current.Or(opt => opt.GlobalId == value.GlobalId && opt.DialogId == value.ConversationId).Expand());
                            List <Message> existingMessages = await context.Messages.Where(messagesCondition).ToListAsync().ConfigureAwait(false);

                            var additionalMessages = MessageConverter.GetMessages(
                                existingDialogMessages.Where(
                                    messageDto => !existingMessages.Any(existing => messageDto.GlobalId == existing.GlobalId &&
                                                                        messageDto.ConversationId == existing.DialogId)));
                            newMessages.AddRange(additionalMessages);
                        }
                        foreach (long userId in nonExistingUsersId)
                        {
                            newDialogs.Add(new Dialog
                            {
                                FirstUID  = messagesOwnerId,
                                SecondUID = userId
                            });
                            if (messagesOwnerId != userId)
                            {
                                newDialogs.Add(new Dialog
                                {
                                    FirstUID  = userId,
                                    SecondUID = messagesOwnerId
                                });
                            }
                        }
                        await context.AddRangeAsync(newDialogs).ConfigureAwait(false);

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

                        foreach (var message in newDialogsMessages)
                        {
                            Dialog ownerDialog = newDialogs.FirstOrDefault(opt =>
                                                                           opt.FirstUID == messagesOwnerId &&
                                                                           ((opt.FirstUID == message.SenderId && opt.SecondUID == message.ReceiverId) ||
                                                                            (opt.SecondUID == message.SenderId && opt.FirstUID == message.ReceiverId)));
                            message.ConversationId = ownerDialog.Id;
                        }
                        newMessages.AddRange(MessageConverter.GetMessages(newDialogsMessages));
                        await context.AddRangeAsync(newMessages.OrderBy(opt => opt.SendingTime)).ConfigureAwait(false);

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

                        transaction.Commit();
                        var groupedMessages = newMessages.GroupBy(opt => opt.DialogId.GetValueOrDefault());
                        foreach (var group in groupedMessages)
                        {
                            var lastMessage = group.OrderByDescending(opt => opt.SendingTime).FirstOrDefault();
                            if (lastMessage != null)
                            {
                                ConversationsService.UpdateConversationLastMessageId(group.Key, ConversationType.Dialog, lastMessage.GlobalId);
                            }
                        }
                        return(MessageConverter.GetMessagesDto(newMessages));
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        throw new MessageException("Save messages error.", ex);
                    }
                }
            }
        }
Example #27
0
        public async Task <ChatVm> AddUsersToChatAsync(IEnumerable <long> usersId, long chatId, long userId)
        {
            using (MessengerDbContext context = contextFactory.Create())
            {
                using (var transaction = await context.Database.BeginTransactionAsync().ConfigureAwait(false))
                {
                    Chat chat = await context.Chats.FirstOrDefaultAsync(opt => opt.Id == chatId).ConfigureAwait(false);

                    if (chat == null)
                    {
                        throw new ConversationNotFoundException(chatId);
                    }
                    User requestingUser = await context.Users.FindAsync(userId).ConfigureAwait(false);

                    if (requestingUser == null || requestingUser.Deleted)
                    {
                        throw new AddUserChatException();
                    }
                    ChatUser chatUser = await context.ChatUsers
                                        .FirstOrDefaultAsync(opt => opt.ChatId == chatId && opt.UserId == userId).ConfigureAwait(false);

                    List <ChatUserVm> addedUsers = new List <ChatUserVm>();
                    if (chat.Deleted)
                    {
                        throw new ConversationIsNotValidException();
                    }
                    if (chatUser != null && chatUser.Banned)
                    {
                        throw new ChatUserBlockedException();
                    }
                    if (usersId.Count() == 1 && usersId.FirstOrDefault() == userId)
                    {
                        if (chat.Type == (int)ChatType.Private)
                        {
                            throw new AddUserChatException();
                        }
                        if (chatUser == null)
                        {
                            chatUser = ChatUserConverter.GetNewChatUser(chatId, userId, null);
                            await context.AddAsync(chatUser).ConfigureAwait(false);
                        }
                        else if (chatUser.Deleted)
                        {
                            chatUser.Deleted = false;
                            chatUser.User    = requestingUser;
                            context.Update(chatUser);
                        }
                        if (!chat.NodesId.Contains(NodeSettings.Configs.Node.Id))
                        {
                            createMessagesService.DownloadMessageHistoryAsync(chat.NodesId.FirstOrDefault(), chat.Id, ConversationType.Chat, null, false);
                        }
                        chat.NodesId = chat.NodesId.Append(requestingUser.NodeId.Value).Distinct().ToArray();
                        addedUsers.Add(ChatUserConverter.GetChatUserVm(chatUser));
                    }
                    else
                    {
                        if ((chatUser?.Deleted).GetValueOrDefault(true))
                        {
                            throw new AddUserChatException();
                        }

                        if (await loadUsersService.IsUserBlacklisted(userId, usersId).ConfigureAwait(false))
                        {
                            throw new UserBlockedException();
                        }

                        ExpressionStarter <User> usersCondition = PredicateBuilder.New <User>();
                        usersCondition = usersId.Aggregate(usersCondition,
                                                           (current, value) => current.Or(opt => opt.Id == value).Expand());
                        List <User> existingUsers = await context.Users
                                                    .AsNoTracking()
                                                    .Where(usersCondition)
                                                    .ToListAsync()
                                                    .ConfigureAwait(false);

                        ExpressionStarter <ChatUser> chatUsersCondition = PredicateBuilder.New <ChatUser>();
                        chatUsersCondition = existingUsers.Select(opt => opt.Id).Aggregate(chatUsersCondition,
                                                                                           (current, value) => current.Or(opt => opt.UserId == value && opt.ChatId == chatId).Expand());
                        List <ChatUser> validChatUsers = await context.ChatUsers
                                                         .Where(chatUsersCondition)
                                                         .Include(opt => opt.User)
                                                         .ToListAsync()
                                                         .ConfigureAwait(false);

                        foreach (ChatUser user in validChatUsers)
                        {
                            if (!user.Banned && user.Deleted)
                            {
                                user.Deleted = false;
                                addedUsers.Add(ChatUserConverter.GetChatUserVm(user));
                            }
                        }
                        context.UpdateRange(validChatUsers);
                        List <long>     newChatUsersId = existingUsers.Select(opt => opt.Id).Except(validChatUsers.Select(opt => opt.UserId)).ToList();
                        List <ChatUser> newChatUsers   = newChatUsersId.Select(id => ChatUserConverter.GetNewChatUser(chatId, id, userId)).ToList();
                        chat.NodesId = chat.NodesId?.Concat(existingUsers.Select(opt => opt.NodeId.GetValueOrDefault())).Distinct().ToArray()
                                       ?? existingUsers.Select(opt => opt.NodeId.GetValueOrDefault()).Distinct().ToArray();
                        await context.ChatUsers
                        .AddRangeAsync(newChatUsers)
                        .ConfigureAwait(false);

                        /* foreach (ChatUser user in newChatUsers)
                         * {
                         *   user.User = existingUsers.FirstOrDefault(opt => opt.Id == user.UserId);
                         * }*/
                        addedUsers.AddRange(ChatUserConverter.GetChatUsersVm(newChatUsers));
                    }
                    context.Update(chat);
                    transaction.Commit();
                    await context.SaveChangesAsync()
                    .ConfigureAwait(false);

                    ChatVm resultChat = ChatConverter.GetChatVm(chat);
                    resultChat.Users = addedUsers;
                    return(resultChat);
                }
            }
        }
Example #28
0
        private async Task <List <User> > AddUsersAsync(int count = 5)
        {
            byte[] passwordHash;
            using (SHA512 sha = SHA512.Create())
            {
                passwordHash = sha.ComputeHash(Encoding.UTF8.GetBytes("password"));
            }
            List <User> users = new List <User>();

            for (int i = 0; i < count; i++)
            {
                users.Add(new User
                {
                    About      = RandomExtensions.NextString(100),
                    Birthday   = DateTime.UtcNow,
                    Confirmed  = true,
                    Photo      = RandomExtensions.NextString(20),
                    Deleted    = false,
                    Tag        = RandomExtensions.NextString(10).ToUpper(),
                    NameFirst  = "User",
                    NameSecond = i.ToString(),
                    Emails     = new HashSet <Emails>
                    {
                        new Emails
                        {
                            EmailAddress = $"user_{RandomExtensions.NextString(i)}@test.test"
                        }
                    },
                    Phones = new HashSet <Phones>
                    {
                        new Phones
                        {
                            PhoneNumber = $"+7{RandomExtensions.NextString(10, "1234567890")}"
                        }
                    },
                    Sha512Password  = passwordHash,
                    ContactsPrivacy = 0,
                    NodeId          = 1
                });
            }
            users[4].Deleted   = true;
            users[3].BlackList = new HashSet <BadUser>
            {
                new BadUser
                {
                    BadUid = 1
                }
            };
            await _context.Users.AddRangeAsync(users);

            await _context.SaveChangesAsync();

            return(users);
        }
Example #29
0
        public async Task <PollDto> VotePollAsync(Guid pollId, long conversationId, ConversationType conversationType, List <PollVoteVm> options, long votingUserId)
        {
            if (!await conversationsService.IsUserInConversationAsync(conversationType, conversationId, votingUserId).ConfigureAwait(false))
            {
                throw new PermissionDeniedException("User is not in conversation.");
            }
            using (MessengerDbContext context = contextFactory.Create())
            {
                var poll = await context.Polls
                           .Include(opt => opt.Options)
                           .ThenInclude(opt => opt.PollOptionVotes)
                           .FirstOrDefaultAsync(opt =>
                                                opt.PollId == pollId &&
                                                opt.ConvertsationId == conversationId &&
                                                opt.ConversationType == conversationType)
                           .ConfigureAwait(false);

                if (poll == null)
                {
                    throw new ObjectDoesNotExistsException($"Poll not found (Poll Id: {pollId}, {conversationType.ToString()}Id: {conversationId}).");
                }
                if (options == null || !options.Any())
                {
                    foreach (var option in poll.Options)
                    {
                        option.PollOptionVotes = option.PollOptionVotes.Where(vote => vote.UserId != votingUserId).ToList();
                    }
                }
                List <PollOptionVote> newVotes     = new List <PollOptionVote>();
                List <PollOptionVote> removedVotes = new List <PollOptionVote>();
                foreach (var voteOption in options)
                {
                    var option = poll.Options.FirstOrDefault(opt => opt.OptionId == voteOption.OptionId);
                    if (option != null && voteOption.Sign != null && voteOption.Sign.Data != null)
                    {
                        if (!option.PollOptionVotes.Any(vote => vote.UserId == votingUserId))
                        {
                            if (poll.SignRequired)
                            {
                                if (voteOption.Sign == null || voteOption.Sign.Data == null || !voteOption.Sign.Data.Any())
                                {
                                    throw new InvalidSignException($"Vote №{voteOption.OptionId} is not signed.");
                                }
                                var signKey = await context.Keys
                                              .FirstOrDefaultAsync(key => key.KeyId == voteOption.Sign.KeyId && key.Type == KeyType.SignAsymKey)
                                              .ConfigureAwait(false);

                                if (signKey == null)
                                {
                                    throw new ObjectDoesNotExistsException($"Key not found (Key Id: {voteOption.Sign.KeyId}.");
                                }
                            }
                            newVotes.Add(new PollOptionVote
                            {
                                ConversationId   = conversationId,
                                ConversationType = conversationType,
                                OptionId         = voteOption.OptionId,
                                UserId           = votingUserId,
                                PollId           = pollId,
                                Sign             = voteOption.Sign?.Data,
                                SignKeyId        = voteOption.Sign?.KeyId
                            });
                        }
                        else
                        {
                            removedVotes.Add(option.PollOptionVotes
                                             .FirstOrDefault(opt => opt.UserId == votingUserId && opt.OptionId == voteOption.OptionId));
                        }
                    }
                    else
                    {
                        if (!option.PollOptionVotes.Any(vote => vote.UserId == votingUserId))
                        {
                            newVotes.Add(new PollOptionVote
                            {
                                ConversationId   = conversationId,
                                ConversationType = conversationType,
                                OptionId         = voteOption.OptionId,
                                UserId           = votingUserId,
                                PollId           = pollId
                            });
                        }
                        else
                        {
                            removedVotes.Add(option.PollOptionVotes
                                             .FirstOrDefault(opt => opt.UserId == votingUserId && opt.OptionId == voteOption.OptionId));
                        }
                    }
                    foreach (var vote in newVotes)
                    {
                        option.PollOptionVotes.Add(vote);
                    }
                    foreach (var vote in removedVotes)
                    {
                        option.PollOptionVotes.Remove(vote);
                    }
                }
                if (!poll.MultipleSelection && poll.Options.Count(opt => opt.PollOptionVotes.Any(vote => vote.UserId == votingUserId)) > 1)
                {
                    throw new InvalidOperationException("Multiple voting is not allowed in current poll.");
                }
                context.Polls.Update(poll);
                await context.SaveChangesAsync().ConfigureAwait(false);

                return(PollConverter.GetPollDto(poll));
            }
        }
Example #30
0
        public async Task <GroupDto> CreateOrEditGroupAsync(GroupDto groupDto)
        {
            try
            {
                using (MessengerDbContext context = contextFactory.Create())
                {
                    Group result;
                    var   group = await context.Groups
                                  .Include(opt => opt.ContactGroups)
                                  .ThenInclude(opt => opt.Contact)
                                  .FirstOrDefaultAsync(opt => opt.UserId == groupDto.UserId && opt.GroupId == groupDto.GroupId)
                                  .ConfigureAwait(false);

                    if (group == null)
                    {
                        Group newGroup = new Group
                        {
                            PrivacySettings = groupDto.PrivacySettings,
                            Title           = groupDto.Title,
                            UserId          = groupDto.UserId,
                            GroupId         = groupDto.GroupId
                        };
                        if (groupDto.UsersId != null && groupDto.UsersId.Any())
                        {
                            var contacts = await context.Contacts
                                           .Where(opt => opt.UserId == groupDto.UserId && groupDto.UsersId.Contains(opt.ContactUserId))
                                           .ToListAsync()
                                           .ConfigureAwait(false);

                            HashSet <ContactGroup> contactGroups = contacts
                                                                   .Select(opt => new ContactGroup {
                                ContactId = opt.ContactId
                            })
                                                                   .ToHashSet();
                            newGroup.ContactGroups = contactGroups;
                        }
                        await context.Groups.AddAsync(newGroup).ConfigureAwait(false);

                        result = newGroup;
                    }
                    else
                    {
                        group.PrivacySettings = groupDto.PrivacySettings;
                        group.Title           = groupDto.Title;
                        context.Update(group);
                        result = group;
                    }
                    await context.SaveChangesAsync().ConfigureAwait(false);

                    return(GroupConverter.GetGroupDto(result));
                }
            }
            catch (PostgresException ex)
            {
                if (ex.SqlState == "23503")
                {
                    throw new ObjectDoesNotExistsException("User is not exists.", ex);
                }
                throw new InternalErrorException("Database error.", ex);
            }
        }