///<summary>Updates password info in db for given inputs if PlainTextPassword (Item2) is not empty. ///Insert EhrMeasureEvent OnlineAccessProvided if previous db version of UserWeb had no PasswordHash (access has now been granted to portal). ///Returns true if UserWeb row was updated. Otherwise returns false.</summary> public static bool UpdateNewPatientPortalCredentials(Tuple <UserWeb, string, PasswordContainer> args) { //No need to check RemotingRole; no call to db. if (args == null) { return(false); } UserWeb userWeb = args.Item1; string passwordPlainText = args.Item2; PasswordContainer loginDetails = args.Item3; if (userWeb != null && !string.IsNullOrEmpty(passwordPlainText)) { //Only insert an EHR event if the password was previously blank (meaning they don't currently have access). if (string.IsNullOrEmpty(userWeb.PasswordHash)) { EhrMeasureEvents.Insert(new EhrMeasureEvent() { DateTEvent = DateTime.Now, EventType = EhrMeasureEventType.OnlineAccessProvided, PatNum = userWeb.FKey, //PatNum. MoreInfo = "", }); } //New password was created so set the flag for the user to change on next login and update the db accordingly. userWeb.RequirePasswordChange = true; userWeb.LoginDetails = loginDetails; UserWebs.Update(userWeb); return(true); } return(false); }
///<summary>Creates a username that is not yet in use. Should typically call UserWebs.GetNewPatientPortalCredentials() instead. ///If you are not inserting the name into UserWeb immediately then listExcludedNames should persist across multiple calls.</summary> public static string CreateUserNameFromPat(Patient pat, UserWebFKeyType fkeyType, List <string> listExcludedNames) { //No need to check RemotingRole; no call to db. string retVal = ""; bool isUserNameOk = false; int i = 0; while (!isUserNameOk) { retVal = pat.FName + ODRandom.Next(100, 100000); if (!UserWebs.UserNameExists(retVal, fkeyType)) { if (!listExcludedNames.Contains(retVal)) { isUserNameOk = true; } } if (i > 1000) { throw new CodeBase.ODException(Lans.g("UserWebs", "Unable to create username for patient.")); } i++; } return(retVal); }
///<summary>Generates a username and password if necessary for this patient. If the patient already has access to the Patient Portal or if they ///are not eligible to be given access, this will return null.</summary> public static UserWeb GetNewPatientPortalCredentials(Patient pat, bool doUpdateDatabase, out string passwordGenerated) { //No need to check RemotingRole; no call to db. passwordGenerated = ""; if (string.IsNullOrEmpty(PrefC.GetString(PrefName.PatientPortalURL))) { return(null); //Haven't set up patient portal yet. } string errors; if (!UserWebs.ValidatePatientAccess(pat, out errors)) { return(null); //Patient is missing necessary fields. } UserWeb userWeb = UserWebs.GetByFKeyAndType(pat.PatNum, UserWebFKeyType.PatientPortal); if (userWeb == null) { userWeb = new UserWeb(); userWeb.UserName = UserWebs.CreateUserNameFromPat(pat, UserWebFKeyType.PatientPortal); userWeb.FKey = pat.PatNum; userWeb.FKeyType = UserWebFKeyType.PatientPortal; userWeb.RequireUserNameChange = true; userWeb.Password = ""; userWeb.IsNew = true; if (doUpdateDatabase) { UserWebs.Insert(userWeb); } } if (!string.IsNullOrEmpty(userWeb.Password) && //If they already have access to the Patient Portal, return. !userWeb.RequirePasswordChange) //If they need to change their password, we are going to generate another password for them. { return(null); } if (string.IsNullOrEmpty(userWeb.Password) && //Only insert an EHR event if their password is blank (meaning they don't currently have access). doUpdateDatabase) { EhrMeasureEvent newMeasureEvent = new EhrMeasureEvent(); newMeasureEvent.DateTEvent = DateTime.Now; newMeasureEvent.EventType = EhrMeasureEventType.OnlineAccessProvided; newMeasureEvent.PatNum = pat.PatNum; newMeasureEvent.MoreInfo = ""; EhrMeasureEvents.Insert(newMeasureEvent); } passwordGenerated = UserWebs.GenerateRandomPassword(8); userWeb.Password = Userods.HashPassword(passwordGenerated, false); userWeb.RequirePasswordChange = true; if (doUpdateDatabase) { UserWebs.Update(userWeb); } return(userWeb); }
///<summary>Updates a password for a given UserWeb account and saves it to the database. Suggested hash type is SHA3-512.</summary> public static bool UpdatePasswordUserWeb(UserWeb user, string inputPass, HashTypes hashType = HashTypes.SHA3_512) { //No need to check RemotingRole; no call to db. user.LoginDetails = GenerateLoginDetails(inputPass, hashType); try { UserWebs.Update(user); } catch { return(false); } return(true); }
///<summary>Creates a username that is not yet in use.</summary> public static string CreateUserNameFromPat(Patient pat, UserWebFKeyType fkeyType) { //No need to check RemotingRole; no call to db. string retVal = ""; bool userNameFound = false; Random rand = new Random(); int i = 0; while (!userNameFound) { retVal = pat.FName + rand.Next(100, 100000); if (!UserWebs.UserNameExists(retVal, fkeyType)) { userNameFound = true; } if (i > 1000) { throw new CodeBase.ODException(Lans.g("UserWebs", "Unable to create username for patient.")); } i++; } return(retVal); }
///<summary>Generates a username and password if necessary for this patient. If the patient is not eligible to be given access, this will return null. ///Otherwise returns the UserWeb (Item1), PlainTextPassword (Item2), PasswordContainer (Item3). ///If PlainTextPassword (Item2) is empty then assume new password generation was not necessary. ///Will insert a new UserWeb if none found for this Patient. Will leave UserWeb.PasswordHash blank. ///Call UpdateNewPatientPortalCredentials() using results of this method if you want to save password to db.</summary> ///<param name="passwordOverride">If a password has already been generated for this patient, pass it in here so that the password returned ///will match.</param> public static Tuple <UserWeb, string, PasswordContainer> GetNewPatientPortalCredentials(Patient pat, string passwordOverride = "") { //No need to check RemotingRole; no call to db. if (string.IsNullOrEmpty(PrefC.GetString(PrefName.PatientPortalURL))) { return(null); //Haven't set up patient portal yet. } string errors; if (!UserWebs.ValidatePatientAccess(pat, out errors)) { return(null); //Patient is missing necessary fields. } UserWeb userWeb = UserWebs.GetByFKeyAndType(pat.PatNum, UserWebFKeyType.PatientPortal); if (userWeb == null) { userWeb = new UserWeb() { UserName = UserWebs.CreateUserNameFromPat(pat, UserWebFKeyType.PatientPortal, new List <string>()), FKey = pat.PatNum, FKeyType = UserWebFKeyType.PatientPortal, RequireUserNameChange = true, LoginDetails = new PasswordContainer(HashTypes.None, "", ""), IsNew = true, }; //Always insert here. We may not ever end up updating UserWeb.PasswordHash if an email is not sent to this patient. //This will leave a UserWeb row with a UserName (for next time) but no password. This row will be updated with a password at the appropriate time. UserWebs.Insert(userWeb); } bool isNewPasswordRequired = false; if (string.IsNullOrEmpty(userWeb.UserName)) //Fixing B11013 so new UserName and Password should be generated. { userWeb.UserName = UserWebs.CreateUserNameFromPat(pat, UserWebFKeyType.PatientPortal, new List <string>()); userWeb.RequireUserNameChange = true; //UserName fields have been changed so update db. UserWebs.Update(userWeb); isNewPasswordRequired = true; } if (userWeb.RequirePasswordChange) //Could be a new UserWeb or a subsequent invite being generated for the same patient (had a second appointment). { isNewPasswordRequired = true; } if (string.IsNullOrEmpty(userWeb.PasswordHash)) //Patient has no password so portal access has not been previously granted. { isNewPasswordRequired = true; } string passwordPlainText = ""; PasswordContainer loginDetails = userWeb.LoginDetails; if (isNewPasswordRequired) { //PP invites will often times call this method and get this far but not actually want to save the new creds to the db. //For that reason we won't actually update the db with the new password here. //The caller of this method will need to call ProcessNewPatientPortalCredentialsOut() if they really want this new password to persist to the db. passwordPlainText = passwordOverride == "" ? UserWebs.GenerateRandomPassword(8) : passwordOverride; loginDetails = Authentication.GenerateLoginDetails(passwordPlainText, HashTypes.SHA3_512); } return(new Tuple <UserWeb, string, PasswordContainer>(userWeb, passwordPlainText, loginDetails)); }