Пример #1
0
        /// <inheritdoc />
        public RequestResult <UserComment> Add(UserComment userComment)
        {
            UserProfile profile = this.profileDelegate.GetUserProfile(userComment.UserProfileId).Payload;
            string?     key     = profile.EncryptionKey;

            if (key == null)
            {
                this.logger.LogError($"User does not have a key: ${userComment.UserProfileId}");
                return(new RequestResult <UserComment>()
                {
                    ResultStatus = ResultType.Error,
                    ResultError = new RequestResultError()
                    {
                        ResultMessage = "Profile Key not set", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    },
                });
            }

            Comment comment = userComment.ToDbModel(this.cryptoDelegate, key);

            DBResult <Comment>          dbComment = this.commentDelegate.Add(comment);
            RequestResult <UserComment> result    = new RequestResult <UserComment>()
            {
                ResourcePayload = UserComment.CreateFromDbModel(dbComment.Payload, this.cryptoDelegate, key),
                ResultStatus    = dbComment.Status == DBStatusCode.Created ? ResultType.Success : ResultType.Error,
                ResultError     = new RequestResultError()
                {
                    ResultMessage = dbComment.Message, ErrorCode = ErrorTranslator.ServiceError(ErrorType.CommunicationInternal, ServiceType.Database)
                },
            };

            return(result);
        }
Пример #2
0
        /// <inheritdoc />
        public RequestResult <IEnumerable <UserComment> > GetEntryComments(string hdId, string parentEntryId)
        {
            UserProfile profile = this.profileDelegate.GetUserProfile(hdId).Payload;
            string?     key     = profile.EncryptionKey;

            // Check that the key has been set
            if (key == null)
            {
                this.logger.LogError($"User does not have a key: ${hdId}");
                return(new RequestResult <IEnumerable <UserComment> >()
                {
                    ResultStatus = ResultType.Error,
                    ResultError = new RequestResultError()
                    {
                        ResultMessage = "Profile Key not set", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    },
                });
            }

            DBResult <IEnumerable <Comment> >          dbComments = this.commentDelegate.GetByParentEntry(hdId, parentEntryId);
            RequestResult <IEnumerable <UserComment> > result     = new RequestResult <IEnumerable <UserComment> >()
            {
                ResourcePayload  = UserComment.CreateListFromDbModel(dbComments.Payload, this.cryptoDelegate, key),
                TotalResultCount = dbComments.Payload.Count(),
                PageIndex        = 0,
                PageSize         = dbComments.Payload.Count(),
                ResultStatus     = dbComments.Status == DBStatusCode.Read ? ResultType.Success : ResultType.Error,
                ResultError      = dbComments.Status != DBStatusCode.Read ? new RequestResultError()
                {
                    ResultMessage = dbComments.Message, ErrorCode = ErrorTranslator.ServiceError(ErrorType.CommunicationInternal, ServiceType.Database)
                } : null,
            };

            return(result);
        }
Пример #3
0
 /// <summary>
 /// Formats the error from the given error type.
 /// </summary>
 /// <param name="message">The user friendly message.</param>
 /// <param name="actionType">Action type that caused the issue.</param>
 /// <returns>A RequestResultError encapsulating the action required.</returns>
 public static HealthGateway.Common.Models.RequestResultError ActionRequired(string message, ActionType actionType)
 {
     return(new Models.RequestResultError()
     {
         ResultMessage = message,
         ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState),
         ActionCode = actionType,
     });
 }
        public async void ShouldInsertUserProfileWithClosedRegistration()
        {
            Tuple <RequestResult <UserProfileModel>, UserProfileModel> result = await ExecuteInsertUserProfile(DBStatusCode.Error, RegistrationStatus.Closed, null);

            var actualResult = result.Item1;

            Assert.Equal(ResultType.Error, actualResult.ResultStatus);
            Assert.Equal(ErrorTranslator.InternalError(ErrorType.InvalidState), actualResult.ResultError.ErrorCode);
            Assert.Equal("Registration is closed", actualResult.ResultError.ResultMessage);
        }
Пример #5
0
        /// <inheritdoc />
        public PrimitiveRequestResult <bool> ValidateEmail(string hdid, Guid inviteKey)
        {
            this.logger.LogTrace($"Validating email... {inviteKey}");
            PrimitiveRequestResult <bool> retVal = new ();

            MessagingVerification?emailVerification = this.messageVerificationDelegate.GetLastByInviteKey(inviteKey);

            if (emailVerification == null ||
                emailVerification.HdId != hdid ||
                emailVerification.Validated == true ||
                emailVerification.Deleted == true)
            {
                // Invalid Verification Attempt
                emailVerification = this.messageVerificationDelegate.GetLastForUser(hdid, MessagingVerificationType.Email);
                if (emailVerification != null &&
                    !emailVerification.Validated)
                {
                    emailVerification.VerificationAttempts++;
                    this.messageVerificationDelegate.Update(emailVerification);
                }

                return(new PrimitiveRequestResult <bool>()
                {
                    ResultStatus = ResultType.Error,
                    ResultError = new RequestResultError()
                    {
                        ResultMessage = "Invalid Email Verification",
                        ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState),
                    },
                });
            }
            else if (emailVerification.VerificationAttempts >= this.maxVerificationAttempts ||
                     emailVerification.ExpireDate < DateTime.UtcNow)
            {
                // Verification Expired
                retVal.ResultStatus = ResultType.ActionRequired;
                retVal.ResultError  = ErrorTranslator.ActionRequired("Email Verification Expired", ActionType.Expired);
            }
            else
            {
                emailVerification.Validated = true;
                this.messageVerificationDelegate.Update(emailVerification);
                UserProfile userProfile = this.profileDelegate.GetUserProfile(hdid).Payload;
                userProfile.Email = emailVerification.Email !.To; // Gets the user email from the email sent.
                this.profileDelegate.Update(userProfile);

                // Update the notification settings
                this.notificationSettingsService.QueueNotificationSettings(new NotificationSettingsRequest(userProfile, userProfile.Email, userProfile.SMSNumber));

                retVal.ResultStatus = ResultType.Success;
            }

            this.logger.LogDebug($"Finished validating email: {JsonConvert.SerializeObject(retVal)}");
            return(retVal);
        }
Пример #6
0
        /// <inheritdoc />
        public RequestResult <IEnumerable <UserNote> > GetNotes(string hdId, int page = 0, int pageSize = 500)
        {
            int offset = page * pageSize;
            DBResult <IEnumerable <Note> > dbNotes = this.noteDelegate.GetNotes(hdId, offset, pageSize);

            UserProfile profile = this.profileDelegate.GetUserProfile(hdId).Payload;
            string?     key     = profile.EncryptionKey;

            // If there is no key yet, generate one and store it in the profile. Only valid while not all profiles have a encryption key.
            if (key == null)
            {
                this.logger.LogInformation($"First time note retrieval with key for user ${hdId}");
                key     = this.EncryptFirstTime(profile, dbNotes.Payload);
                dbNotes = this.noteDelegate.GetNotes(hdId, offset, pageSize);
            }

            // Check that the key has been set
            if (key == null)
            {
                this.logger.LogError($"User does not have a key: ${hdId}");
                return(new RequestResult <IEnumerable <UserNote> >()
                {
                    ResultStatus = ResultType.Error,
                    ResultError = new RequestResultError()
                    {
                        ResultMessage = "Profile Key not set", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    },
                });
            }

            RequestResult <IEnumerable <UserNote> > result = new RequestResult <IEnumerable <UserNote> >()
            {
                ResourcePayload  = UserNote.CreateListFromDbModel(dbNotes.Payload, this.cryptoDelegate, key),
                PageIndex        = page,
                PageSize         = pageSize,
                TotalResultCount = dbNotes.Payload.ToList().Count,
                ResultStatus     = dbNotes.Status == DBStatusCode.Read ? ResultType.Success : ResultType.Error,
                ResultError      = dbNotes.Status == DBStatusCode.Read ? null : new RequestResultError()
                {
                    ResultMessage = dbNotes.Message, ErrorCode = ErrorTranslator.ServiceError(ErrorType.CommunicationInternal, ServiceType.Database)
                },
            };

            return(result);
        }
        /// <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);
        }
Пример #8
0
        /// <inheritdoc />
        public RequestResult <Communication> Update(Communication communication)
        {
            if (communication.EffectiveDateTime < communication.ExpiryDateTime)
            {
                this.logger.LogTrace($"Updating communication... {JsonSerializer.Serialize(communication)}");

                DBResult <HealthGateway.Database.Models.Communication> dbResult = this.communicationDelegate.Update(communication.ToDbModel());
                return(new RequestResult <Communication>()
                {
                    ResourcePayload = new Communication(dbResult.Payload),
                    ResultStatus = dbResult.Status == DBStatusCode.Updated ? ResultType.Success : ResultType.Error,
                    ResultError = dbResult.Status == DBStatusCode.Updated ? null : new RequestResultError()
                    {
                        ResultMessage = dbResult.Message, ErrorCode = ErrorTranslator.ServiceError(ErrorType.CommunicationInternal, ServiceType.Database)
                    },
                });
            }
            else
            {
                return(new RequestResult <Communication>()
                {
                    ResourcePayload = null,
                    ResultStatus = ResultType.Error,
                    ResultError = new RequestResultError()
                    {
                        ResultMessage = "Effective Date should be before Expiry Date.", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    },
                });
            }
        }
Пример #9
0
        /// <inheritdoc />
        public RequestResult <Communication> Add(Communication communication)
        {
            this.logger.LogTrace($"Communication recieved:  {JsonSerializer.Serialize(communication)}");
            if (communication.CommunicationTypeCode == CommunicationType.Email)
            {
                if (communication.Text.Length == 0 || communication.Subject.Length == 0)
                {
                    throw new ArgumentException("One of: Email Subject, Email Content is invalid.");
                }

                communication.EffectiveDateTime = DateTime.UtcNow;
                communication.ExpiryDateTime    = DateTime.UtcNow;
            }

            this.logger.LogTrace($"Adding communication... {JsonSerializer.Serialize(communication)}");

            if (communication.EffectiveDateTime < communication.ExpiryDateTime)
            {
                this.logger.LogTrace($"Adding communication... {JsonSerializer.Serialize(communication)}");
                DBResult <HealthGateway.Database.Models.Communication> dbResult = this.communicationDelegate.Add(communication.ToDbModel());
                return(new RequestResult <Communication>()
                {
                    ResourcePayload = new Communication(dbResult.Payload),
                    ResultStatus = dbResult.Status == DBStatusCode.Created ? ResultType.Success : ResultType.Error,
                    ResultError = dbResult.Status == DBStatusCode.Created ? null : new RequestResultError()
                    {
                        ResultMessage = dbResult.Message, ErrorCode = ErrorTranslator.ServiceError(ErrorType.CommunicationInternal, ServiceType.Database)
                    },
                });
            }
            else
            {
                return(new RequestResult <Communication>()
                {
                    ResourcePayload = null,
                    ResultStatus = ResultType.Error,
                    ResultError = new RequestResultError()
                    {
                        ResultMessage = "Effective Date should be before Expiry Date.", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    },
                });
            }
        }
Пример #10
0
        /// <inheritdoc />
        public RequestResult <Communication> Delete(Communication communication)
        {
            if (communication.CommunicationStatusCode == CommunicationStatus.Processed)
            {
                this.logger.LogError($"Processed communication can't be deleted.");
                return(new RequestResult <Communication>()
                {
                    ResultStatus = ResultType.Error,
                    ResultError = new RequestResultError()
                    {
                        ResultMessage = "Processed communication can't be deleted.", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    },
                });
            }

            DBResult <HealthGateway.Database.Models.Communication> dbResult = this.communicationDelegate.Delete(communication.ToDbModel());
            RequestResult <Communication> result = new RequestResult <Communication>()
            {
                ResourcePayload = new Communication(dbResult.Payload),
                ResultStatus    = dbResult.Status == DBStatusCode.Deleted ? ResultType.Success : ResultType.Error,
                ResultError     = dbResult.Status == DBStatusCode.Deleted ? null : new RequestResultError()
                {
                    ResultMessage = dbResult.Message, ErrorCode = ErrorTranslator.ServiceError(ErrorType.CommunicationInternal, ServiceType.Database)
                },
            };

            return(result);
        }
Пример #11
0
        private void ReceiveEvent(object sender, NpgsqlNotificationEventArgs e)
        {
            this.logger.LogInformation($"Event received on channel {Channel}");
            var options = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true,
                IgnoreNullValues            = true,
                WriteIndented = true,
            };

            options.Converters.Add(new JsonStringEnumConverter());
            BannerChangeEvent?changeEvent = JsonSerializer.Deserialize <BannerChangeEvent>(e.Payload, options);

            if (this.CommunicationService != null && changeEvent != null && changeEvent.Data != null)
            {
                DateTime utcnow = DateTime.UtcNow;
                RequestResult <Communication> cacheEntry = new RequestResult <Communication>();
                if (changeEvent.Action == InsertAction ||
                    changeEvent.Action == UpdateAction)
                {
                    Communication comm = changeEvent.Data;
                    if (utcnow >= comm.EffectiveDateTime && utcnow <= comm.ExpiryDateTime)
                    {
                        cacheEntry.ResultStatus    = Common.Constants.ResultType.Success;
                        cacheEntry.ResourcePayload = comm;
                        this.logger.LogInformation("Active Banner inserted or updated in DB");
                        this.CommunicationService.SetActiveBannerCache(cacheEntry);
                    }
                }
                else if (changeEvent.Action == DeleteAction)
                {
                    RequestResult <Communication> currentBanner = this.CommunicationService.GetActiveBanner();
                    if (currentBanner.ResourcePayload != null &&
                        currentBanner.ResourcePayload.Id == changeEvent.Data.Id)
                    {
                        cacheEntry.ResultStatus = Common.Constants.ResultType.Error;
                        cacheEntry.ResultError  = new RequestResultError()
                        {
                            ResultMessage = "Active Banner deleted from DB", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                        };
                        this.logger.LogInformation("Active Banner deleted from DB");
                        this.CommunicationService.SetActiveBannerCache(cacheEntry);
                    }
                }
            }
        }
Пример #12
0
        /// <inheritdoc/>
        public async System.Threading.Tasks.Task <RequestResult <PatientModel> > GetPatient(string identifier, PatientIdentifierType identifierType = PatientIdentifierType.HDID)
        {
            using Activity? activity = Source.StartActivity("GetPatient");
            RequestResult <PatientModel> requestResult = new RequestResult <PatientModel>();
            PatientModel?patient = this.GetFromCache(identifier, identifierType);

            if (patient == null)
            {
                switch (identifierType)
                {
                case PatientIdentifierType.HDID:
                    this.logger.LogDebug("Performing Patient lookup by HDID");
                    requestResult = await this.patientDelegate.GetDemographicsByHDIDAsync(identifier).ConfigureAwait(true);

                    break;

                case PatientIdentifierType.PHN:
                    this.logger.LogDebug("Performing Patient lookup by PHN");
                    requestResult = await this.patientDelegate.GetDemographicsByPHNAsync(identifier).ConfigureAwait(true);

                    break;

                default:
                    this.logger.LogDebug($"Failed Patient lookup unknown PatientIdentifierType");
                    requestResult.ResultStatus = ResultType.Error;
                    requestResult.ResultError  = new RequestResultError()
                    {
                        ResultMessage = $"Internal Error: PatientIdentifierType is unknown '{identifierType.ToString()}'", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                    };
                    break;
                }

                if (requestResult.ResultStatus == ResultType.Success && requestResult.ResourcePayload != null)
                {
                    this.CachePatient(requestResult.ResourcePayload);
                }
            }
            else
            {
                this.logger.LogDebug("Patient fetched from Cache");
                requestResult.ResourcePayload = patient;
                requestResult.ResultStatus    = ResultType.Success;
            }

            activity?.Stop();
            return(requestResult);
        }
        public void ShouldDeleteProcessedCommunicationReturnError()
        {
            // Sample communication to test
            Communication comm = new Communication()
            {
                Id = Guid.NewGuid(),
                CommunicationStatusCode = CommunicationStatus.Processed,
                Text              = "Test update communication",
                Subject           = "Testing update communication",
                EffectiveDateTime = new DateTime(2020, 07, 04),
                ExpiryDateTime    = new DateTime(2020, 07, 07),
            };

            RequestResult <Communication> expectedResult = new RequestResult <Communication>()
            {
                ResultStatus = ResultType.Error,
                ResultError  = new RequestResultError()
                {
                    ResultMessage = "Processed communication can't be deleted.", ErrorCode = ErrorTranslator.InternalError(ErrorType.InvalidState)
                },
            };

            RequestResult <Communication> actualResult = DeleteCommunication(comm, DBStatusCode.Error);

            // Check result
            Assert.True(expectedResult.IsDeepEqual(actualResult));
        }
Пример #14
0
        /// <inheritdoc />
        public async Task <RequestResult <UserProfileModel> > CreateUserProfile(CreateUserRequest createProfileRequest, DateTime jwtAuthTime)
        {
            this.logger.LogTrace($"Creating user profile... {JsonSerializer.Serialize(createProfileRequest)}");

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

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

            // Validate registration age
            string hdid = createProfileRequest.Profile.HdId;
            PrimitiveRequestResult <bool> isMimimunAgeResult = await this.ValidateMinimumAge(hdid).ConfigureAwait(true);

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

            // Create profile
            UserProfile newProfile = new ()
            {
                HdId = hdid,
                IdentityManagementId   = createProfileRequest.Profile.IdentityManagementId,
                AcceptedTermsOfService = createProfileRequest.Profile.AcceptedTermsOfService,
                Email             = string.Empty,
                SMSNumber         = null,
                CreatedBy         = hdid,
                UpdatedBy         = hdid,
                LastLoginDateTime = jwtAuthTime,
                EncryptionKey     = this.cryptoDelegate.GenerateKey(),
            };
            DBResult <UserProfile> insertResult = this.userProfileDelegate.InsertUserProfile(newProfile);

            if (insertResult.Status == DBStatusCode.Created)
            {
                UserProfile createdProfile     = insertResult.Payload;
                string?     requestedSMSNumber = createProfileRequest.Profile.SMSNumber;
                string?     requestedEmail     = createProfileRequest.Profile.Email;

                // Add email verification
                if (!string.IsNullOrWhiteSpace(requestedEmail))
                {
                    this.userEmailService.CreateUserEmail(hdid, requestedEmail);
                }

                // Add SMS verification
                if (!string.IsNullOrWhiteSpace(requestedSMSNumber))
                {
                    this.userSMSService.CreateUserSMS(hdid, requestedSMSNumber);
                }

                this.notificationSettingsService.QueueNotificationSettings(new NotificationSettingsRequest(createdProfile, requestedEmail, requestedSMSNumber));

                this.logger.LogDebug($"Finished creating user profile. {JsonSerializer.Serialize(insertResult)}");
                return(new RequestResult <UserProfileModel>()
                {
                    ResourcePayload = UserProfileModel.CreateFromDbModel(insertResult.Payload),
                    ResultStatus = ResultType.Success,
                });
            }
            else
            {
                this.logger.LogError($"Error creating user profile. {JsonSerializer.Serialize(insertResult)}");
                return(new RequestResult <UserProfileModel>()
                {
                    ResultStatus = ResultType.Error,
                    ResultError = new RequestResultError()
                    {
                        ResultMessage = insertResult.Message,
                        ErrorCode = ErrorTranslator.ServiceError(ErrorType.CommunicationInternal, ServiceType.Database),
                    },
                });
            }
        }