/// <inheritdoc />
 public void Update(MessagingVerification messageVerification)
 {
     this.logger.LogTrace($"Updating email message verification in DB... {JsonSerializer.Serialize(messageVerification)}");
     this.dbContext.Update <MessagingVerification>(messageVerification);
     this.dbContext.SaveChanges();
     this.logger.LogDebug($"Finished updating email message verification in DB. {messageVerification.Id}");
 }
Beispiel #2
0
        public RequestResult <IEnumerable <AdminEmail> > GetEmails()
        {
            int pageIndex = 0;
            DBResult <List <Email> >                  dbEmail      = this.emailDelegate.GetEmails(pageIndex, this.maxEmails);
            IEnumerable <MessagingVerification>       emailInvites = this.emailInviteDelegate.GetAllEmail();
            RequestResult <IEnumerable <AdminEmail> > result       = new RequestResult <IEnumerable <AdminEmail> >()
            {
                ResourcePayload = dbEmail.Payload.Select(e =>
                {
                    MessagingVerification emailInvite = emailInvites.First(ei =>
                                                                           e.To !.Equals(ei.Email?.To, System.StringComparison.CurrentCultureIgnoreCase));
                    string inviteStatus = GetEmailInviteStatus(emailInvite);
                    return(AdminEmail.CreateFromDbModel(e, inviteStatus));
                }),
                PageIndex        = pageIndex,
                PageSize         = this.maxEmails,
                TotalResultCount = dbEmail.Payload.Count,
                ResultStatus     = dbEmail.Status == DBStatusCode.Read ? ResultType.Success : ResultType.Error,
                ResultError      = dbEmail.Status == DBStatusCode.Read ? null : new RequestResultError()
                {
                    ResultMessage = dbEmail.Message, ErrorCode = ErrorTranslator.ServiceError(ErrorType.CommunicationInternal, ServiceType.Database)
                },
            };

            return(result);
        }
Beispiel #3
0
        public void ShouldValidateSMSWithInvalidInvite()
        {
            var smsValidationCode = "SMSValidationCodeMock";
            MessagingVerification expectedResult = new MessagingVerification
            {
                HdId = "invalid" + HdIdMock,
                VerificationAttempts = 0,
                SMSValidationCode    = smsValidationCode,
                ExpireDate           = DateTime.Now.AddDays(1),
            };

            Mock <IMessagingVerificationDelegate> messagingVerificationDelegate = new Mock <IMessagingVerificationDelegate>();

            messagingVerificationDelegate.Setup(s => s.GetLastForUser(It.IsAny <string>(), It.IsAny <string>())).Returns(expectedResult);

            Mock <IUserProfileDelegate> userProfileDelegate = new Mock <IUserProfileDelegate>();
            var userProfileMock = new Database.Wrapper.DBResult <UserProfile>()
            {
                Payload = new UserProfile(),
                Status  = Database.Constants.DBStatusCode.Read,
            };

            userProfileDelegate.Setup(s => s.GetUserProfile(It.IsAny <string>())).Returns(userProfileMock);
            userProfileDelegate.Setup(s => s.Update(It.IsAny <UserProfile>(), It.IsAny <bool>())).Returns(new Database.Wrapper.DBResult <UserProfile>());

            IUserSMSService service = new UserSMSService(
                new Mock <ILogger <UserSMSService> >().Object,
                messagingVerificationDelegate.Object,
                userProfileDelegate.Object,
                new Mock <INotificationSettingsService>().Object);

            bool actualResult = service.ValidateSMS(HdIdMock, smsValidationCode);

            Assert.True(!actualResult);
        }
        /// <inheritdoc />
        public bool UpdateUserSMS(string hdid, string sms, Uri hostUri, string bearerToken)
        {
            this.logger.LogTrace($"Removing user sms number ${hdid}");
            UserProfile userProfile = this.profileDelegate.GetUserProfile(hdid).Payload;

            userProfile.SMSNumber = null;
            this.profileDelegate.Update(userProfile);
            MessagingVerification?smsInvite = this.RetrieveLastInvite(hdid);

            // Update the notification settings
            NotificationSettingsRequest notificationRequest = this.UpdateNotificationSettings(userProfile, userProfile.Email, sms);

            if (smsInvite != null)
            {
                this.logger.LogInformation($"Expiring old sms validation for user ${hdid}");
                smsInvite.ExpireDate = DateTime.UtcNow;
                smsInvite.Deleted    = string.IsNullOrEmpty(sms);
                this.messageVerificationDelegate.Update(smsInvite);
            }

            if (!string.IsNullOrEmpty(sms))
            {
                this.logger.LogInformation($"Sending new sms invite for user ${hdid}");
                MessagingVerification messagingVerification = new MessagingVerification();
                messagingVerification.HdId              = hdid;
                messagingVerification.SMSNumber         = sms;
                messagingVerification.SMSValidationCode = notificationRequest.SMSVerificationCode;
                messagingVerification.VerificationType  = MessagingVerificationType.SMS;
                messagingVerification.ExpireDate        = DateTime.UtcNow.AddDays(VerificationExpiryDays);
                this.messageVerificationDelegate.Insert(messagingVerification);
            }

            this.logger.LogDebug($"Finished updating user sms");
            return(true);
        }
        /// <inheritdoc />
        public void Expire(MessagingVerification messageVerification, bool markDeleted)
        {
            messageVerification.ExpireDate = DateTime.UtcNow;
            messageVerification.Deleted    = markDeleted;
            this.Update(messageVerification);

            this.logger.LogDebug("Finished Expiring messaging verification from DB.");
        }
Beispiel #6
0
        private static string GetEmailInviteStatus(MessagingVerification emailInvite)
        {
            if (emailInvite == null)
            {
                return(UserInviteStatus.NotInvited);
            }

            return(emailInvite.Validated ? UserInviteStatus.InvitedValidated : UserInviteStatus.InvitedNotValidated);
        }
        /// <inheritdoc />
        public void QueueNewInviteEmail(MessagingVerification invite)
        {
            if (invite.Email == null || string.IsNullOrWhiteSpace(invite.Email.To))
            {
                throw new ArgumentNullException(nameof(invite), "Invite Email To cannot be null or whitespace");
            }

            this.logger.LogTrace($"Queueing new invite email... {JsonConvert.SerializeObject(invite)}");
            this.emailInviteDelegate.Insert(invite);
            this.jobClient.Enqueue <IEmailJob>(j => j.SendEmail(invite.Email.Id));
            this.logger.LogDebug($"Finished queueing new invite email. {invite.Id}");
        }
        /// <inheritdoc />
        public Guid Insert(MessagingVerification messageVerification)
        {
            this.logger.LogTrace($"Inserting message verification to DB... {JsonSerializer.Serialize(messageVerification)}");
            if (messageVerification.VerificationType == MessagingVerificationType.Email && messageVerification.Email == null)
            {
                throw new ArgumentException("Email cannot be null when verification type is Email");
            }
            else if (messageVerification.VerificationType == MessagingVerificationType.SMS &&
                     (string.IsNullOrWhiteSpace(messageVerification.SMSNumber) || string.IsNullOrWhiteSpace(messageVerification.SMSValidationCode)))
            {
                throw new ArgumentException("SMSNumber/SMSValidationCode cannot be null or empty when verification type is SMS");
            }

            this.dbContext.Add <MessagingVerification>(messageVerification);
            this.dbContext.SaveChanges();
            this.logger.LogDebug($"Finished inserting message verification to DB. {messageVerification.Id}");
            return(messageVerification.Id);
        }
        /// <inheritdoc />
        public void QueueNewInviteEmail(string hdid, string toEmail, Uri activationHost)
        {
            Dictionary <string, string> keyValues = new Dictionary <string, string>();
            MessagingVerification       invite    = new MessagingVerification();

            invite.InviteKey  = Guid.NewGuid();
            invite.HdId       = hdid;
            invite.ExpireDate = DateTime.UtcNow.AddDays(VerificationExpiryDays);

            string hostUrl = activationHost.ToString();

            hostUrl = hostUrl.Remove(hostUrl.Length - 1, 1); // Strips last slash

            keyValues.Add(INVITE_KEY_VARIABLE, invite.InviteKey.ToString());
            keyValues.Add(ACTIVATION_HOST_VARIABLE, hostUrl);

            invite.Email = this.ProcessTemplate(toEmail, this.GetEmailTemplate(EmailTemplateName.RegistrationTemplate), keyValues);
            this.QueueNewInviteEmail(invite);
        }
        /// <inheritdoc />
        public RequestResult <List <string> > SendInvites(List <string> betaRequestIds, string referer)
        {
            this.logger.LogTrace($"Sending invites to beta requests... {JsonConvert.SerializeObject(betaRequestIds)}");

            // Get the requets that still need to be invited
            List <BetaRequest> pendingRequests = this.betaRequestDelegate.GetPendingBetaRequest().Payload;

            List <BetaRequest> requestsToInvite = pendingRequests.Where(b => betaRequestIds.Contains(b.HdId)).ToList();

            RequestResult <List <string> > requestResult = new RequestResult <List <string> >();

            requestResult.ResourcePayload = new List <string>();
            foreach (BetaRequest betaRequest in requestsToInvite)
            {
                MessagingVerification invite = new MessagingVerification();
                invite.InviteKey  = Guid.NewGuid();
                invite.HdId       = betaRequest.HdId;
                invite.ExpireDate = DateTime.MaxValue;

                Dictionary <string, string> keyValues = new Dictionary <string, string>();
                keyValues.Add(HostTemplateVariable, referer);
                keyValues.Add(InviteKeyTemplateVariable, invite.InviteKey.ToString());
                keyValues.Add(EmailToTemplateVariable, betaRequest.EmailAddress);
                invite.Email = this.emailQueueService.ProcessTemplate(betaRequest.EmailAddress, this.emailQueueService.GetEmailTemplate(EmailTemplateName.InviteTemplate), keyValues);
                this.emailQueueService.QueueNewInviteEmail(invite);

                requestResult.ResourcePayload.Add(betaRequest.HdId);
                requestResult.ResultStatus = ResultType.Success;
            }

            this.logger.LogDebug("Finished sending beta requests invites.");
            this.logger.LogDebug($"Requets to invite: {JsonConvert.SerializeObject(betaRequestIds)}");
            this.logger.LogDebug($"Invited: {JsonConvert.SerializeObject(requestResult.ResourcePayload)}");
            requestResult.ResultStatus = ResultType.Success;

            return(requestResult);
        }
        /// <inheritdoc />
        public async Task <RequestResult <UserProfileModel> > CreateUserProfile(CreateUserRequest createProfileRequest, Uri hostUri, string bearerToken)
        {
            this.logger.LogTrace($"Creating user profile... {JsonSerializer.Serialize(createProfileRequest)}");

            string registrationStatus = this.configurationService.GetConfiguration().WebClient.RegistrationStatus;

            RequestResult <UserProfileModel> requestResult = new RequestResult <UserProfileModel>();

            if (registrationStatus == RegistrationStatus.Closed)
            {
                requestResult.ResultStatus = ResultType.Error;
                requestResult.ResultError  = new RequestResultError()
                {
                    ResultMessage = "Registration is closed", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                };
                this.logger.LogWarning($"Registration is closed. {JsonSerializer.Serialize(createProfileRequest)}");
                return(requestResult);
            }

            string hdid = createProfileRequest.Profile.HdId;
            MessagingVerification?emailInvite = null;

            if (registrationStatus == RegistrationStatus.InviteOnly)
            {
                if (!Guid.TryParse(createProfileRequest.InviteCode, out Guid inviteKey))
                {
                    requestResult.ResultStatus = ResultType.Error;
                    requestResult.ResultError  = new RequestResultError()
                    {
                        ResultMessage = "Invalid email invite", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    };
                    this.logger.LogWarning($"Invalid email invite code. {JsonSerializer.Serialize(createProfileRequest)}");
                    return(requestResult);
                }

                emailInvite = this.emailInviteDelegate.GetByInviteKey(inviteKey);
                bool hdidIsValid = string.IsNullOrEmpty(emailInvite?.HdId) || (emailInvite?.HdId == createProfileRequest.Profile.HdId);

                // Fails if...
                // Email invite not found or
                // Email invite was already validated or
                // Email's recipient is not found
                // Email invite must have a blank/null HDID or be the same as the one in the request
                // Email address doesn't match the invite
                if (emailInvite == null || (emailInvite.Email == null || emailInvite.Email.To == null ||
                                            emailInvite.Validated || !hdidIsValid ||
                                            !emailInvite.Email.To.Equals(createProfileRequest.Profile.Email, StringComparison.OrdinalIgnoreCase)))
                {
                    requestResult.ResultStatus = ResultType.Error;
                    requestResult.ResultError  = new RequestResultError()
                    {
                        ResultMessage = "Invalid email invite", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    };
                    this.logger.LogWarning($"Invalid email invite. {JsonSerializer.Serialize(createProfileRequest)}");
                    return(requestResult);
                }
            }

            PrimitiveRequestResult <bool> isMimimunAgeResult = await this.ValidateMinimumAge(hdid).ConfigureAwait(true);

            if (isMimimunAgeResult.ResultStatus != ResultType.Success)
            {
                requestResult.ResultStatus = isMimimunAgeResult.ResultStatus;
                requestResult.ResultError  = isMimimunAgeResult.ResultError;
                return(requestResult);
            }
            else if (!isMimimunAgeResult.ResourcePayload)
            {
                requestResult.ResultStatus = ResultType.Error;
                requestResult.ResultError  = new RequestResultError()
                {
                    ResultMessage = "Patient under minimum age", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                };
                this.logger.LogWarning($"Patient under minimum age. {JsonSerializer.Serialize(createProfileRequest)}");
                return(requestResult);
            }

            string?     requestedSMSNumber = createProfileRequest.Profile.SMSNumber;
            string?     requestedEmail     = createProfileRequest.Profile.Email;
            UserProfile newProfile         = createProfileRequest.Profile;

            newProfile.Email         = string.Empty;
            newProfile.SMSNumber     = null;
            newProfile.CreatedBy     = hdid;
            newProfile.UpdatedBy     = hdid;
            newProfile.EncryptionKey = this.cryptoDelegate.GenerateKey();

            DBResult <UserProfile> insertResult = this.userProfileDelegate.InsertUserProfile(newProfile);

            if (insertResult.Status == DBStatusCode.Created)
            {
                // Update the notification settings
                NotificationSettingsRequest notificationRequest = this.UpdateNotificationSettings(newProfile, requestedSMSNumber);

                if (emailInvite != null)
                {
                    // Validates the invite email
                    emailInvite.Validated = true;
                    emailInvite.HdId      = hdid;
                    this.emailInviteDelegate.Update(emailInvite);
                }

                if (!string.IsNullOrWhiteSpace(requestedEmail))
                {
                    this.emailQueueService.QueueNewInviteEmail(hdid, requestedEmail, hostUri);
                }

                if (!string.IsNullOrWhiteSpace(requestedSMSNumber))
                {
                    this.logger.LogInformation($"Sending sms invite for user ${hdid}");
                    MessagingVerification messagingVerification = new MessagingVerification();
                    messagingVerification.HdId              = hdid;
                    messagingVerification.SMSNumber         = requestedSMSNumber;
                    messagingVerification.SMSValidationCode = notificationRequest.SMSVerificationCode;
                    messagingVerification.VerificationType  = MessagingVerificationType.SMS;
                    messagingVerification.ExpireDate        = DateTime.MaxValue;
                    this.messageVerificationDelegate.Insert(messagingVerification);
                }

                requestResult.ResourcePayload = UserProfileModel.CreateFromDbModel(insertResult.Payload);
                requestResult.ResultStatus    = ResultType.Success;
            }

            this.logger.LogDebug($"Finished creating user profile. {JsonSerializer.Serialize(insertResult)}");
            return(requestResult);
        }
        private async Task <Tuple <RequestResult <UserProfileModel>, UserProfileModel> > ExecuteInsertUserProfile(Database.Constants.DBStatusCode dbResultStatus, string registrationStatus, MessagingVerification messagingVerification = null)
        {
            UserProfile userProfile = new UserProfile
            {
                HdId = hdid,
                AcceptedTermsOfService = true,
                Email = "*****@*****.**"
            };

            UserProfileModel expected = UserProfileModel.CreateFromDbModel(userProfile);

            Mock <IUserProfileDelegate> profileDelegateMock = new Mock <IUserProfileDelegate>();

            profileDelegateMock.Setup(s => s.InsertUserProfile(It.Is <UserProfile>(x => x.HdId == userProfile.HdId))).Returns(new DBResult <UserProfile>
            {
                Payload = userProfile,
                Status  = DBStatusCode.Created
            });

            Mock <IConfigurationService> configServiceMock = new Mock <IConfigurationService>();

            configServiceMock.Setup(s => s.GetConfiguration()).Returns(new ExternalConfiguration()
            {
                WebClient = new WebClientConfiguration()
                {
                    RegistrationStatus = registrationStatus
                }
            });

            Mock <ICryptoDelegate> cryptoDelegateMock = new Mock <ICryptoDelegate>();

            cryptoDelegateMock.Setup(s => s.GenerateKey()).Returns("abc");

            Mock <INotificationSettingsService> notificationServiceMock = new Mock <INotificationSettingsService>();

            notificationServiceMock.Setup(s => s.QueueNotificationSettings(It.IsAny <NotificationSettingsRequest>()));

            IUserProfileService service = new UserProfileService(
                new Mock <ILogger <UserProfileService> >().Object,
                new Mock <IPatientService>().Object,
                new Mock <IUserEmailService>().Object,
                new Mock <IUserSMSService>().Object,
                configServiceMock.Object,
                new Mock <IEmailQueueService>().Object,
                notificationServiceMock.Object,
                profileDelegateMock.Object,
                new Mock <IUserPreferenceDelegate>().Object,
                new Mock <ILegalAgreementDelegate>().Object,
                new Mock <IMessagingVerificationDelegate>().Object,
                cryptoDelegateMock.Object,
                new Mock <IHttpContextAccessor>().Object);

            RequestResult <UserProfileModel> actualResult = await service.CreateUserProfile(new CreateUserRequest()
            {
                Profile = userProfile
            }, DateTime.Today);

            return(new Tuple <RequestResult <UserProfileModel>, UserProfileModel>(actualResult, expected));
        }