/// <summary> /// Gets the PersonToken by impersonation token (rckipid) /// </summary> /// <param name="impersonationToken">The impersonation token.</param> /// <returns></returns> public PersonToken GetByImpersonationToken(string impersonationToken) { // the impersonationToken should normally be a UrlEncoded string, but it is possible that the caller already UrlDecoded it, so first try without UrlDecoding it var decryptedToken = Rock.Security.Encryption.DecryptString(impersonationToken); if (decryptedToken == null) { // do a Replace('!', '%') on the token before UrlDecoding because we did a Replace('%', '!') after we UrlEncoded it (to make it embeddable in HTML and cross browser compatible) string urlDecodedKey = System.Web.HttpUtility.UrlDecode(impersonationToken.Replace('!', '%')); decryptedToken = Rock.Security.Encryption.DecryptString(urlDecodedKey); } var personToken = this.Queryable().Include(pt => pt.PersonAlias).FirstOrDefault(a => a.Token == decryptedToken); if (personToken == null) { bool tokenUseLegacyFallback = GlobalAttributesCache.Get().GetValue("core.PersonTokenUseLegacyFallback").AsBoolean(); if (tokenUseLegacyFallback) { var legacyPerson = new PersonService(this.Context as Data.RockContext).GetByLegacyEncryptedKey(impersonationToken, true); if (legacyPerson == null || !legacyPerson.IsPersonTokenUsageAllowed()) { return(null); } if (legacyPerson != null) { // if LegacyFallback is enabled, and we found a person, create a fake PersonToken personToken = new PersonToken { PersonAlias = legacyPerson.PrimaryAlias, ExpireDateTime = null, PageId = null, LastUsedDateTime = RockDateTime.Now, UsageLimit = null }; } } else { return(null); } } var person = new PersonService(this.Context as Data.RockContext).Get(personToken.PersonAlias.PersonId); if (!person.IsPersonTokenUsageAllowed()) { return(null); } return(personToken); }
/// <summary> /// Clones this PersonToken object to a new PersonToken object /// </summary> /// <param name="source">The source.</param> /// <param name="deepCopy">if set to <c>true</c> a deep copy is made. If false, only the basic entity properties are copied.</param> /// <returns></returns> public static PersonToken Clone(this PersonToken source, bool deepCopy) { if (deepCopy) { return(source.Clone() as PersonToken); } else { var target = new PersonToken(); target.CopyPropertiesFrom(source); return(target); } }
/// <summary> /// Clones this PersonToken object to a new PersonToken object with default values for the properties in the Entity and Model base classes. /// </summary> /// <param name="source">The source.</param> /// <returns></returns> public static PersonToken CloneWithoutIdentity(this PersonToken source) { var target = new PersonToken(); target.CopyPropertiesFrom(source); target.Id = 0; target.Guid = Guid.NewGuid(); target.ForeignKey = null; target.ForeignId = null; target.ForeignGuid = null; return(target); }
/// <summary> /// Copies the properties from another PersonToken object to this PersonToken object /// </summary> /// <param name="target">The target.</param> /// <param name="source">The source.</param> public static void CopyPropertiesFrom(this PersonToken target, PersonToken source) { target.Id = source.Id; target.ExpireDateTime = source.ExpireDateTime; target.ForeignGuid = source.ForeignGuid; target.ForeignKey = source.ForeignKey; target.LastUsedDateTime = source.LastUsedDateTime; target.PageId = source.PageId; target.PersonAliasId = source.PersonAliasId; target.TimesUsed = source.TimesUsed; target.UsageLimit = source.UsageLimit; target.Guid = source.Guid; target.ForeignId = source.ForeignId; }
/// <summary> /// Updates the last login and writes to the person's history log /// </summary> /// <param name="userName">Name of the user.</param> public static void UpdateLastLogin(string userName) { if (!string.IsNullOrWhiteSpace(userName)) { using (var rockContext = new RockContext()) { int? personId = null; bool impersonated = userName.StartsWith("rckipid="); if (!impersonated) { var userLogin = new UserLoginService(rockContext).GetByUserName(userName); if (userLogin != null) { userLogin.LastLoginDateTime = RockDateTime.Now; personId = userLogin.PersonId; } } else { var impersonationToken = userName.Substring(8); personId = new PersonService(rockContext).GetByImpersonationToken(impersonationToken, false, null)?.Id; } if (personId.HasValue) { var relatedDataBuilder = new System.Text.StringBuilder(); int?relatedEntityTypeId = null; int?relatedEntityId = null; if (impersonated) { var impersonatedByUser = HttpContext.Current?.Session["ImpersonatedByUser"] as UserLogin; relatedEntityTypeId = EntityTypeCache.GetId <Rock.Model.Person>(); relatedEntityId = impersonatedByUser?.PersonId; if (impersonatedByUser != null) { relatedDataBuilder.Append($" impersonated by { impersonatedByUser.Person.FullName }"); } } if (HttpContext.Current != null && HttpContext.Current.Request != null) { string cleanUrl = PersonToken.ObfuscateRockMagicToken(HttpContext.Current.Request.Url.AbsoluteUri); // obfuscate the url specified in the returnurl, just in case it contains any sensitive information (like a rckipid) Regex returnurlRegEx = new Regex(@"returnurl=([^&]*)"); cleanUrl = returnurlRegEx.Replace(cleanUrl, "returnurl=XXXXXXXXXXXXXXXXXXXXXXXXXXXX"); relatedDataBuilder.AppendFormat(" to <span class='field-value'>{0}</span>, from <span class='field-value'>{1}</span>", cleanUrl, HttpContext.Current.Request.UserHostAddress); } var historyChangeList = new History.HistoryChangeList(); var historyChange = historyChangeList.AddChange(History.HistoryVerb.Login, History.HistoryChangeType.Record, userName); if (relatedDataBuilder.Length > 0) { historyChange.SetRelatedData(relatedDataBuilder.ToString(), null, null); } HistoryService.SaveChanges(rockContext, typeof(Rock.Model.Person), Rock.SystemGuid.Category.HISTORY_PERSON_ACTIVITY.AsGuid(), personId.Value, historyChangeList, true); } } } }
/// <summary> /// Updates the last login, writes to the person's history log, and saves changes to the database /// </summary> /// <param name="userName">Name of the user.</param> public static void UpdateLastLogin(string userName) { if (string.IsNullOrWhiteSpace(userName)) { return; } int? personId = null; bool impersonated = userName.StartsWith("rckipid="); using (var rockContext = new RockContext()) { if (!impersonated) { var userLogin = new UserLoginService(rockContext).Queryable().Where(a => a.UserName == userName).FirstOrDefault(); if (userLogin != null) { userLogin.LastLoginDateTime = RockDateTime.Now; personId = userLogin.PersonId; rockContext.SaveChanges(); } } else { var impersonationToken = userName.Substring(8); personId = new PersonService(rockContext).GetByImpersonationToken(impersonationToken, false, null)?.Id; } } if (personId == null) { return; } var relatedDataBuilder = new System.Text.StringBuilder(); int?relatedEntityTypeId = null; int?relatedEntityId = null; if (impersonated) { var impersonatedByUser = HttpContext.Current?.Session?["ImpersonatedByUser"] as UserLogin; relatedEntityTypeId = EntityTypeCache.GetId <Rock.Model.Person>(); relatedEntityId = impersonatedByUser?.PersonId; if (impersonatedByUser != null) { relatedDataBuilder.Append($" impersonated by { impersonatedByUser.Person.FullName }"); } } if (HttpContext.Current != null && HttpContext.Current.Request != null) { string cleanUrl = PersonToken.ObfuscateRockMagicToken(HttpContext.Current.Request.UrlProxySafe().AbsoluteUri); // obfuscate the URL specified in the returnurl, just in case it contains any sensitive information (like a rckipid) Regex returnurlRegEx = new Regex(@"returnurl=([^&]*)"); cleanUrl = returnurlRegEx.Replace(cleanUrl, "returnurl=XXXXXXXXXXXXXXXXXXXXXXXXXXXX"); string clientIPAddress; try { clientIPAddress = Rock.Web.UI.RockPage.GetClientIpAddress(); } catch { // if we get an exception getting the IP Address, just ignore it clientIPAddress = ""; } relatedDataBuilder.AppendFormat( " to <span class='field-value'>{0}</span>, from <span class='field-value'>{1}</span>", cleanUrl, clientIPAddress); } var historyChangeList = new History.HistoryChangeList(); var historyChange = historyChangeList.AddChange(History.HistoryVerb.Login, History.HistoryChangeType.Record, userName); if (relatedDataBuilder.Length > 0) { historyChange.SetRelatedData(relatedDataBuilder.ToString(), null, null); } var historyList = HistoryService.GetChanges(typeof(Rock.Model.Person), Rock.SystemGuid.Category.HISTORY_PERSON_ACTIVITY.AsGuid(), personId.Value, historyChangeList, null, null, null, null, null); if (historyList.Any()) { Task.Run(async() => { // Wait 1 second to allow all post save actions to complete await Task.Delay(1000); try { using (var rockContext = new RockContext()) { rockContext.BulkInsert(historyList); } } catch (SystemException ex) { ExceptionLogService.LogException(ex, null); } }); } }
/// <summary> /// Creates a new interaction. /// </summary> /// <param name="interactionComponentId">The interaction component identifier.</param> /// <param name="entityId">The entity identifier.</param> /// <param name="operation">The operation.</param> /// <param name="interactionSummary">The interaction summary.</param> /// <param name="interactionData">The interaction data.</param> /// <param name="personAliasId">The person alias identifier.</param> /// <param name="dateTime">The date time.</param> /// <param name="deviceApplication">The device application.</param> /// <param name="deviceOs">The device os.</param> /// <param name="deviceClientType">Type of the device client.</param> /// <param name="deviceTypeData">The device type data.</param> /// <param name="ipAddress">The ip address.</param> /// <param name="browserSessionId">The browser session identifier.</param> /// <returns></returns> public Interaction CreateInteraction(int interactionComponentId, int?entityId, string operation, string interactionSummary, string interactionData, int?personAliasId, DateTime dateTime, string deviceApplication, string deviceOs, string deviceClientType, string deviceTypeData, string ipAddress, Guid?browserSessionId) { Interaction interaction = new Interaction(); interaction.InteractionComponentId = interactionComponentId; interaction.EntityId = entityId; interaction.Operation = operation; interaction.InteractionData = interactionData.IsNotNullOrWhiteSpace() ? PersonToken.ObfuscateRockMagicToken(interactionData) : string.Empty; interaction.InteractionDateTime = dateTime; interaction.PersonAliasId = personAliasId; interaction.InteractionSummary = interactionSummary; int?deviceTypeId = null; if (deviceApplication.IsNotNullOrWhiteSpace() && deviceOs.IsNotNullOrWhiteSpace() && deviceClientType.IsNotNullOrWhiteSpace()) { var deviceType = this.GetInteractionDeviceType(deviceApplication, deviceOs, deviceClientType, deviceTypeData); deviceTypeId = deviceType != null ? deviceType.Id : ( int? )null; } // If we don't have an BrowserSessionId, IPAddress or a devicetype, there is nothing useful about the session // but at least one of these has a value, then we should lookup or create a session if (browserSessionId.HasValue || ipAddress.IsNotNullOrWhiteSpace() || deviceTypeId.HasValue) { var session = this.GetInteractionSession(browserSessionId, ipAddress, deviceTypeId); interaction.InteractionSessionId = session.Id; } return(interaction); }
/// <summary> /// Updates the last login and writes to the person's history log /// </summary> /// <param name="userName">Name of the user.</param> public static void UpdateLastLogin(string userName) { if (!string.IsNullOrWhiteSpace(userName)) { using (var rockContext = new RockContext()) { int? personId = null; bool impersonated = userName.StartsWith("rckipid="); if (!impersonated) { var userLogin = new UserLoginService(rockContext).GetByUserName(userName); if (userLogin != null) { userLogin.LastLoginDateTime = RockDateTime.Now; personId = userLogin.PersonId; } } else { var impersonationToken = userName.Substring(8); personId = new PersonService(rockContext).GetByImpersonationToken(impersonationToken, false, null)?.Id; } if (personId.HasValue) { var summary = new System.Text.StringBuilder(); if (impersonated) { summary.Append("Impersonated user logged in"); var impersonatedByUser = HttpContext.Current?.Session["ImpersonatedByUser"] as UserLogin; if (impersonatedByUser != null) { summary.Append($" ( impersonated by { impersonatedByUser.Person.FullName } ) "); } } else { summary.AppendFormat("User logged in with <span class='field-name'>{0}</span> username", userName); } if (HttpContext.Current != null && HttpContext.Current.Request != null) { string cleanUrl = PersonToken.ObfuscateRockMagicToken(HttpContext.Current.Request.Url.AbsoluteUri); // obfuscate the url specified in the returnurl, just in case it contains any sensitive information (like a rckipid) Regex returnurlRegEx = new Regex(@"returnurl=([^&]*)"); cleanUrl = returnurlRegEx.Replace(cleanUrl, "returnurl=XXXXXXXXXXXXXXXXXXXXXXXXXXXX"); summary.AppendFormat(", to <span class='field-value'>{0}</span>, from <span class='field-value'>{1}</span>", cleanUrl, HttpContext.Current.Request.UserHostAddress); } summary.Append("."); var historyService = new HistoryService(rockContext); var personEntityTypeId = EntityTypeCache.Read("Rock.Model.Person").Id; var activityCategoryId = CategoryCache.Read(Rock.SystemGuid.Category.HISTORY_PERSON_ACTIVITY.AsGuid(), rockContext).Id; historyService.Add(new History { EntityTypeId = personEntityTypeId, CategoryId = activityCategoryId, EntityId = personId.Value, Summary = summary.ToString(), Verb = "LOGIN" }); } rockContext.SaveChanges(); } } }
/// <summary> /// Creates and stores a new PersonToken for a person using the specified ExpireDateTime, UsageLimit, and Page /// Returns the encrypted URLEncoded Token which can be used as a rckipid /// </summary> /// <param name="personAlias">The person alias.</param> /// <param name="expireDateTime">The expire date time.</param> /// <param name="usageLimit">The usage limit.</param> /// <param name="pageId">The page identifier.</param> /// <returns></returns> public static string CreateNew(PersonAlias personAlias, DateTime?expireDateTime, int?usageLimit, int?pageId) { if (personAlias == null) { return(null); } using (var rockContext = new RockContext()) { var person = personAlias.Person; if (person == null) { person = new PersonService(rockContext).Get(personAlias.PersonId); } if (person == null) { return(null); } // If a token is disallowed by security settings, return an error message. if (!person.IsPersonTokenUsageAllowed()) { return("TokenProhibited"); } var token = Rock.Security.Encryption.GenerateUniqueToken(); PersonToken personToken = new PersonToken(); personToken.PersonAliasId = personAlias.Id; personToken.Token = token; if (expireDateTime != null) { personToken.ExpireDateTime = expireDateTime; } else { int?tokenExpireMinutes = GlobalAttributesCache.Get().GetValue("core.PersonTokenExpireMinutes").AsIntegerOrNull(); if (tokenExpireMinutes.HasValue) { personToken.ExpireDateTime = RockDateTime.Now.AddMinutes(tokenExpireMinutes.Value); } else { personToken.ExpireDateTime = null; } } personToken.TimesUsed = 0; personToken.UsageLimit = usageLimit ?? GlobalAttributesCache.Get().GetValue("core.PersonTokenUsageLimit").AsIntegerOrNull(); personToken.PageId = pageId; var personTokenService = new PersonTokenService(rockContext); personTokenService.Add(personToken); rockContext.SaveChanges(true); var encryptedToken = Rock.Security.Encryption.EncryptString(token); // do a Replace('%', '!') after we UrlEncode it (to make it more safely embeddable in HTML and cross browser compatible) return(System.Web.HttpUtility.UrlEncode(encryptedToken).Replace('%', '!')); } }