////------------------------------------------------------------------------------------------------------------------------------------------------------------- ///// <summary> ///// If deleteExisting groups is true the entered group type will overwrite ///// any existing groups assigned to this user. (This is require where ///// a user can only belong to one group) ///// </summary> ///// <param name="updatedUser"></param> ///// <param name="groupType"></param> ///// <param name="deleteExistingGroups"></param> ///// <returns></returns> //public bool EditUserPassword(int userID, SecureString Password, MGGroupType groupType, bool p) { // bool result = false; // try { // result = SecurityOperations.UpdateUserPassword(userID, Password, Authorisation.UseMGLRatherThanMySQLPasswordEncryption); // if (result) { // DateTime pWordChangeTimeStamp = DateTime.Now; // SecurityOperations.UpdatePasswordChangeDate(userID, pWordChangeTimeStamp); // // 13-Jul-2015 - lets email the user to confirm that their password has changed! // MGUser u = null; // Authorisation.GetUser(userID, out u); // SecurityOperations.PasswordChangedEmailUser(u, pWordChangeTimeStamp); // } // } catch (Exception ex) { // Logger.Log("Error in UserAdministration.AddUser." + ex.Message); // } finally { // SecurityOperations.Finish(); // } // return result; //} //------------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// If deleteExisting groups is true the entered group type will overwrite /// any existing groups assigned to this user. (This is require where /// a user can only belong to one group) /// </summary> /// <param name="updatedUser"></param> /// <param name="groupType"></param> /// <param name="deleteExistingGroups"></param> /// <returns></returns> public bool EditUserDetails(MGUser updatedUser, MGGroupType groupType, bool p) { bool result = false; try { result = SecurityOperations.UpdateUserDetails(updatedUser.ID, updatedUser.Username, updatedUser.Email, updatedUser.JobTitle, updatedUser.Organisation, updatedUser.OrganisationID, updatedUser.Telephone); //need to add the user to the user_groups xref's result = result && SecurityOperations.DeleteUsersGroupXrefs(updatedUser.ID); result = result && SecurityOperations.UpdateUserToGroupXref(updatedUser.Username, groupType); //need to update the applications user to group to xref's if (result) { UserOperations userOps = new UserOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); Dictionary <int, List <int> > userGroupDict = userOps.UserGroupDictionary(); userOps.Finish(); MGLApplicationSecurityInterface.Instance().UserGroupXref = userGroupDict; } } catch (Exception ex) { Logger.LogError(8, "Error in UserAdministration.AddUser." + ex.Message); } finally { SecurityOperations.Finish(); } return(result); }
//------------------------------------------------------------------------------------------------------------------------------------------------------------- public List <MGUser> GetUsers(string filterByType, string filterByValue, string sortColumn, List <string> PreviousSortColumnNames, System.Web.UI.WebControls.SortDirection sortDirection) { List <MGUser> result = new List <MGUser>(); UserOperations userOps = null; bool isLockAcquired = Monitor.TryEnter(USER_ADMIN_LOCK_OBJ, USER_ADMIN_LOCK_TIMEOUT); if (isLockAcquired) { try { userOps = new UserOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); result = userOps.GetAllUsers(filterByType, filterByValue, sortColumn, PreviousSortColumnNames, sortDirection); } catch (Exception ex) { Logger.LogError(8, "Error in UserAdministration.GetUsers." + ex.Message); } finally { Monitor.Exit(USER_ADMIN_LOCK_OBJ); if (userOps != null) { userOps.Finish(); } } } return(result); }
//------------------------------------------------------------------------------------------------------------------------------------------------------------- public List <MGUser> GetUsers(List <string> fieldsToSearch, string valueToSearch, string sortColumnName, System.Web.UI.WebControls.SortDirection sortDirection) { List <MGUser> result = new List <MGUser>(); UserOperations userOps = null; bool isLockAcquired = Monitor.TryEnter(USER_ADMIN_LOCK_OBJ, USER_ADMIN_LOCK_TIMEOUT); if (isLockAcquired) { try { userOps = new UserOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); result = userOps.GetAllUsers(fieldsToSearch, valueToSearch, sortColumnName, sortDirection); } catch (Exception ex) { Logger.LogError(8, "Error in UserAdministration.GetUsers (Without PreviousSortColumnNames)." + ex.Message); } finally { Monitor.Exit(USER_ADMIN_LOCK_OBJ); if (userOps != null) { userOps.Finish(); } } } else { Logger.LogError(8, "Failed to get exclusive lock in GetUsers to read the Users table!"); return(result); } return(result); }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------- public static List <MGGroup> AllGroups() { // Get all the Groups List <MGGroup> allGroups = null; GroupOperations groupOps = null; try { groupOps = new GroupOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); allGroups = groupOps.GetAllGroups(); } catch (Exception ex) { Logger.LogError(5, "Problem getting all groups at " + ex); return(null); } finally { if (groupOps != null) { groupOps.Finish(); } } return(allGroups); }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------- public static List <MGUser> AllUsers() { // Get all the Users List <MGUser> allUsers = null; UserOperations userOps = null; try { userOps = new UserOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); allUsers = userOps.GetAllUsers(); } catch (Exception ex) { Logger.LogError(9, "Problem getting all users at " + ex); return(null); } finally { if (userOps != null) { userOps.Finish(); } } return(allUsers); }
//----------------------------------------------------------------------------------------------------------------------------------------------------------- public List <SecureString> GetEmailsInGroup(string groupName) { // get a list of all the users emails List <SecureString> aUserEmails = new List <SecureString>(); // get the group ID int gID = 0; foreach (MGGroup group in MGLApplicationSecurityInterface.Instance().Groups) { if (group.Name.Equals(groupName, StringComparison.CurrentCultureIgnoreCase)) { gID = group.ID; break; } } // get the email address of all the users, if they belong to this group foreach (int uID in MGLApplicationSecurityInterface.Instance().Users.Keys) { List <int> groupIDs = null; MGLApplicationSecurityInterface.Instance().UserGroupXref.TryGetValue(uID, out groupIDs); if (groupIDs != null && groupIDs.Contains(gID)) { MGUser u; MGLApplicationSecurityInterface.Instance().Users.TryGetValue(uID, out u); aUserEmails.Add(u.Email); } } return(aUserEmails); }
//----------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Called the first time the login page is requested. For security, on new logins, the current session should be /// abandoned and a new session started. /// /// Calls the login page back with the ResetSession and an encrypted CID token which contains the AnonID /// cookie value (a GUID) and a date time stamp /// /// </summary> protected void Step1KillSession() { string redirectURL = MGLApplicationSecurityInterface.Instance().AppLoginConfig.DefaultPostLoginPage; try { //-----1----- Abandon the current session // 20-Apr-2016 - Before killing the session lets make absolutely sure that the current Session ID has been removed from the HTTPS checks // This should be entirely unnecessary and does appear to be so, but lets do it anyway as it is light, fast and important //Logger.Log("XXXXX - "+ActionPage+".aspx - removing the session requires https for " + Session.SessionID + " BEFORE Killing the session...."); if (MGLApplicationInterface.Instance().UseHttpsSessionsIndependently == true) { MGLApplicationInterface.Instance().RemoveSessionRequiringHTTPS(Session.SessionID); MGLSessionInterface.Instance().UseHTTPS = false; } // And then lets abandon the session properly Session.Abandon(); Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", "")); //-----2----- Build the encrypted string StringBuilder authKey = GenerateKey(); //-----3----- Build the redirectURL, including the special action, next page URL and CID authorisation token // For the independent HTTPS in sessions we need to call this page again to configure the new session and then continue // otherwise we can just go with it ... string redirectPage = (MGLApplicationInterface.Instance().UseHttpsSessionsIndependently == false) ? ActionPage + "Do.aspx" : ActionPage + ".aspx"; redirectURL = BuildRedirectURL(redirectPage, authKey); } catch (Exception ex) { Logger.LogError(8, "Problem setting the authorisation redirect url in the login page. This is serious! The specific error was: " + ex.ToString()); } //-----4----- Redirect to the loginDo page and commence the login event in anger. // Or if this a use-https-in-sessions-independently website, lets come back to the login page to reconfigure. Response.Redirect(redirectURL); }
//------------------------------------------------------------------------------------------------------------------------------------------------------------- public MGUser GetUserByEmail(SecureString email) { MGUser result = new MGUser(); UserOperations userOps = new UserOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); try { result = userOps.GetUserByEmail(email); } catch (Exception ex) { Logger.LogError(8, "Error in UserAdministration.GetUserByEmail b at " + ex); } finally { userOps.Finish(); } return(result); }
//------------------------------------------------------------------------------------------------------------------------------------------------------------- public MGUser GetUser(int selectedUserID) { MGUser result = new MGUser(); UserOperations userOps = new UserOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); try { result = userOps.GetUser(selectedUserID); } catch (Exception ex) { Logger.LogError(8, "Error in UserAdministration.GetUser by id." + ex.Message); } finally { userOps.Finish(); } return(result); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- public bool DeleteUser(int userID) { bool result = false; UserOperations userOps = new UserOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); try { result = userOps.DeleteUser(userID); result = result && userOps.DeleteUsersGroupXrefs(userID); } catch (Exception ex) { Logger.LogError(8, "Error in UserAdministration.DeleteUser." + ex.Message); } finally { userOps.Finish(); } return(result); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- //Create as a static method so this can be called using // just the class name (no object instance is required). // It simplifies other code because it will always return // the single instance of this class, either newly created // or from the application public static MGLApplicationSecurityInterface Instance() { MGLApplicationSecurityInterface appSingleton; //This allows us to switch which application object // we are using for secure/non-secure sessions string APPLICATION_CACHE = APP_SINGLETON; if (null == System.Web.HttpContext.Current.Application[APPLICATION_CACHE]) { //No current Application object exists, use private constructor to // create an instance, place it into the Application appSingleton = new MGLApplicationSecurityInterface(); System.Web.HttpContext.Current.Application[APPLICATION_CACHE] = appSingleton; } else { //Retrieve the already instance that was already created appSingleton = (MGLApplicationSecurityInterface)System.Web.HttpContext.Current.Application[APPLICATION_CACHE]; } return(appSingleton); }
//----------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Called the second time the login page is requested. For security, on new logins, the current session should be /// abandoned and a new session started. /// /// If HTTPS is globally all false or globally all true, this intermediate step is not required as the page requesting the login page will /// have the same protocol (both HTTP or both HTTPS). However, if the MGLApplicationInterface.UseHttpsSessionsIndependently variable is set, then we need /// an intermediate step - this step - to force the session to use HTTPs and then call LoginDo... /// /// Calls the LoginDo page with the ResetSession and an encrypted CID token which contains the AnonID /// cookie value ( a GUID) and a date time stamp. /// /// </summary> protected void Step2SetSecureSession(StringBuilder encryptedKey) { string redirectURL = MGLApplicationSecurityInterface.Instance().AppLoginConfig.DefaultPostLoginPage; try { bool keyIsValid = KeyIsValid(encryptedKey); //Logger.Log("XXXXX - "+ActionPage+".aspx - Setting the secure session. And checking that the key is valid: " + keyIsValid); //-----a----- Get the AuthKey and check it is legit - if not we do nothing and the user is bounced out to the default page if (keyIsValid == true) { //-----b----- Setup the new session to be secure - which by now should have been created as this page loads for the second time! // Force this session to use HTTPs as this page has been requested if (MGLSessionInterface.Instance().UseHTTPS == false) { MGLSessionInterface.Instance().SetSessionRequiresHTTPs(Request.Cookies["AnonID"], Session.SessionID, HttpContext.Current.Request.IsLocal); } //-----c----- Build the URL for the LoginDo page - and if HTTPS is enabled, we explicitly set the LoginDo page to use HTTPS // ASSUMPTION is that the action page HAS TO BE IN THE Code/Security folder!! string redirectPage = ActionPage + "Do.aspx"; if (MGLSessionInterface.Instance().UseHTTPS == true && HttpContext.Current.Request.IsLocal == false) { redirectPage = "https://" + MGLSessionInterface.Instance().Config.WebProjectPath() + "Code/Security/" + redirectPage; } redirectURL = BuildRedirectURL(redirectPage, encryptedKey); } } catch (Exception ex) { Logger.LogError(8, "Problem setting the secure session in the login page. This is serious! The specific error was: " + ex.ToString()); } //Logger.Log("XXXXX - " + ActionPage + ".aspx - https is " + MGLSessionInterface.Instance().UseHTTPS + " and Redirecting to : " + redirectURL); //-----d----- Redirect to the LoginDo page and commence the login event in anger ... Response.Redirect(redirectURL); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- public UserAdministration(int timezoneOffset) { SecurityOperations = new BaseSecurityOperations(MGLApplicationSecurityInterface.Instance().DatabaseConfig); }
//--------------------------------------------------------------------------------------------------------------------------------------------------------------- // public bool Login( User user, string password) { public bool Login(SecureString userName, SecureString password) { bool loggedIn = false; string loginError = "Username or password not recognised."; UserOperations userOps = null; try { if (userName != null) { userOps = new UserOperations(lcf); MGUser user = userOps.GetUser(userName); // check the number of logins has not been exceeded if (user != null) { if (user.IsLockedOut == true) { loginError = "Too many incorrect attempts. Please contact the web team."; // to unlock your account."; } else { // 30-Nov-2015 - Strip the password out of the user information as this is applied to the session user.Password = null; // Check the password if (MGLApplicationSecurityInterface.Instance().AppLoginConfig.EnableAutomatedLogin == false && password != null) { // check the user name and the encrypted password in the database bool userLoginDetailsCorrect = userOps.UserLoginDetailsCorrect(user.Username, password); // if incorrect, increment the incorrect logins // if correct, increment the total logins userOps.LogLogin(user.ID, userLoginDetailsCorrect); // reextract the user as the LastIP and login date will have changed - better to keep this consistent, if its used for validation in the future ... user = userOps.GetUser(user.ID); if (userLoginDetailsCorrect) { loggedIn = true; // Set the current user object in the session loginError = null; MGLSessionSecurityInterface.Instance().CurrentUser = user; } } else { loggedIn = true; // Set the current user object in the session loginError = null; MGLSessionSecurityInterface.Instance().CurrentUser = user; } } if (loggedIn) { SecureContentWrapper.LiveDbContextInstance = new SecureContentWrapper(AppSecurityContext.MainDbLcf); // SecureContentWrapper.StagingDbContextInstance = new SecureContentWrapper(AppSecurityContext.StagingDbLcf); } } } } catch (Exception ex) { Logger.LogError(7, "Problem logging in at " + ex); } finally { if (userOps != null) { userOps.Finish(); } } MGLSessionSecurityInterface.Instance().SecurityError = loginError; return(loggedIn); }