/// <summary> /// Does cleanup of Person Aliases and Metaphones /// </summary> /// <param name="dataMap">The data map.</param> private void PersonCleanup(JobDataMap dataMap) { // Add any missing person aliases var personRockContext = new Rock.Data.RockContext(); PersonService personService = new PersonService(personRockContext); PersonAliasService personAliasService = new PersonAliasService(personRockContext); var personAliasServiceQry = personAliasService.Queryable(); foreach (var person in personService.Queryable("Aliases") .Where(p => !p.Aliases.Any() && !personAliasServiceQry.Any(pa => pa.AliasPersonId == p.Id)) .Take(300)) { person.Aliases.Add(new PersonAlias { AliasPersonId = person.Id, AliasPersonGuid = person.Guid }); } personRockContext.SaveChanges(); // Add any missing metaphones int namesToProcess = dataMap.GetString("MaxMetaphoneNames").AsInteger(); if (namesToProcess > 0) { var firstNameQry = personService.Queryable().Select(p => p.FirstName).Where(p => p != null); var nickNameQry = personService.Queryable().Select(p => p.NickName).Where(p => p != null); var lastNameQry = personService.Queryable().Select(p => p.LastName).Where(p => p != null); var nameQry = firstNameQry.Union(nickNameQry.Union(lastNameQry)); var metaphones = personRockContext.Metaphones; var existingNames = metaphones.Select(m => m.Name).Distinct(); // Get the names that have not yet been processed var namesToUpdate = nameQry .Where(n => !existingNames.Contains(n)) .Take(namesToProcess) .ToList(); foreach (string name in namesToUpdate) { string mp1 = string.Empty; string mp2 = string.Empty; Rock.Utility.DoubleMetaphone.doubleMetaphone(name, ref mp1, ref mp2); var metaphone = new Metaphone(); metaphone.Name = name; metaphone.Metaphone1 = mp1; metaphone.Metaphone2 = mp2; metaphones.Add(metaphone); } personRockContext.SaveChanges(); } }
/// <summary> /// Job that updates the JobPulse setting with the current date/time. /// This will allow us to notify an admin if the jobs stop running. /// /// Called by the <see cref="IScheduler" /> when a /// <see cref="ITrigger" /> fires that is associated with /// the <see cref="IJob" />. /// </summary> public virtual void Execute(IJobExecutionContext context) { // get the job map JobDataMap dataMap = context.JobDetail.JobDataMap; int maxRecords = Int32.Parse( dataMap.GetString( "MaxRecordsPerRun" ) ); int throttlePeriod = Int32.Parse( dataMap.GetString( "ThrottlePeriod" ) ); int retryPeriod = Int32.Parse( dataMap.GetString( "RetryPeriod" ) ); DateTime retryDate = DateTime.Now.Subtract(new TimeSpan(retryPeriod, 0, 0, 0)); var rockContext = new Rock.Data.RockContext(); LocationService locationService = new LocationService(rockContext); var addresses = locationService.Queryable() .Where( l => ( (l.IsGeoPointLocked == null || l.IsGeoPointLocked == false) // don't ever try locked address && (l.IsActive == true && l.Street1 != null && l.PostalCode != null) // or incomplete addresses && ( (l.GeocodedDateTime == null && (l.GeocodeAttemptedDateTime == null || l.GeocodeAttemptedDateTime < retryDate)) // has not been attempted to be geocoded since retry date || (l.StandardizedDateTime == null && (l.StandardizeAttemptedDateTime == null || l.StandardizeAttemptedDateTime < retryDate)) // has not been attempted to be standardize since retry date ) )) .Take( maxRecords ).ToList(); foreach ( var address in addresses ) { locationService.Verify( address, false ); // currently not reverifying rockContext.SaveChanges(); System.Threading.Thread.Sleep( throttlePeriod ); } }
/// <summary> /// Purges the audit log. /// </summary> /// <param name="dataMap">The data map.</param> private void PurgeAuditLog(JobDataMap dataMap) { // purge audit log int?auditExpireDays = dataMap.GetString("AuditLogExpirationDays").AsIntegerOrNull(); if (auditExpireDays.HasValue) { var auditLogRockContext = new Rock.Data.RockContext(); DateTime auditExpireDate = RockDateTime.Now.Add(new TimeSpan(auditExpireDays.Value * -1, 0, 0, 0)); // delete in chunks (see http://dba.stackexchange.com/questions/1750/methods-of-speeding-up-a-huge-delete-from-table-with-no-clauses) bool keepDeleting = true; while (keepDeleting) { var dbTransaction = auditLogRockContext.Database.BeginTransaction(); try { int rowsDeleted = auditLogRockContext.Database.ExecuteSqlCommand(@"DELETE TOP (1000) FROM [Audit] WHERE [DateTime] < @auditExpireDate", new SqlParameter("auditExpireDate", auditExpireDate)); keepDeleting = rowsDeleted > 0; } finally { dbTransaction.Commit(); } } auditLogRockContext.SaveChanges(); } }
public IHttpActionResult UpdateDeviceRegistrationByGuid(Guid personalDeviceGuid, string registration, bool?notificationsEnabled = null) { using (var rockContext = new Rock.Data.RockContext()) { var service = new PersonalDeviceService(rockContext); // MAC address var personalDevice = service.Get(personalDeviceGuid); if (personalDevice == null) { return(NotFound()); } personalDevice.DeviceRegistrationId = registration; if (notificationsEnabled.HasValue) { personalDevice.NotificationsEnabled = notificationsEnabled.Value; } rockContext.SaveChanges(); return(Ok()); } }
/// <summary> /// Cleans up expired entity sets. /// </summary> /// <param name="dataMap">The data map.</param> private void CleanupExpiredEntitySets(JobDataMap dataMap) { var entitySetRockContext = new Rock.Data.RockContext(); var currentDateTime = RockDateTime.Now; var entitySetService = new EntitySetService(entitySetRockContext); var qry = entitySetService.Queryable().Where(a => a.ExpireDateTime.HasValue && a.ExpireDateTime < currentDateTime); foreach (var entitySet in qry.ToList()) { string deleteWarning; if (entitySetService.CanDelete(entitySet, out deleteWarning)) { // delete in chunks (see http://dba.stackexchange.com/questions/1750/methods-of-speeding-up-a-huge-delete-from-table-with-no-clauses) bool keepDeleting = true; while (keepDeleting) { var dbTransaction = entitySetRockContext.Database.BeginTransaction(); try { string sqlCommand = @"DELETE TOP (1000) FROM [EntitySetItem] WHERE [EntitySetId] = @entitySetId"; int rowsDeleted = entitySetRockContext.Database.ExecuteSqlCommand(sqlCommand, new SqlParameter("entitySetId", entitySet.Id)); keepDeleting = rowsDeleted > 0; } finally { dbTransaction.Commit(); } } entitySetService.Delete(entitySet); entitySetRockContext.SaveChanges(); } } }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode"/> /// </summary> /// <param name="codeLength">A <see cref="System.Int32"/> representing the length of the (security) code.</param> /// <returns>A new <see cref="Rock.Model.AttendanceCode"/></returns> public static AttendanceCode GetNew(int codeLength = 3) { string code = string.Empty; var attendanceCode = new AttendanceCode(); var rockContext = new Rock.Data.RockContext(); var service = new AttendanceCodeService( rockContext ); // Make sure only one instance at a time is checking for unique code lock (obj) { // Find a good unique code for today while ( code == string.Empty || noGood.Any( s => s == code ) || service.Get( RockDateTime.Today, code ).Any() ) { code = GenerateRandomCode( codeLength ); } attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add( attendanceCode ); rockContext.SaveChanges(); } return attendanceCode; }
/// <summary> /// Job that updates the JobPulse setting with the current date/time. /// This will allow us to notify an admin if the jobs stop running. /// /// Called by the <see cref="IScheduler" /> when a /// <see cref="ITrigger" /> fires that is associated with /// the <see cref="IJob" />. /// </summary> public virtual void Execute(IJobExecutionContext context) { // get the job map JobDataMap dataMap = context.JobDetail.JobDataMap; int maxRecords = Int32.Parse(dataMap.GetString("MaxRecordsPerRun")); int throttlePeriod = Int32.Parse(dataMap.GetString("ThrottlePeriod")); int retryPeriod = Int32.Parse(dataMap.GetString("RetryPeriod")); DateTime retryDate = DateTime.Now.Subtract(new TimeSpan(retryPeriod, 0, 0, 0)); var rockContext = new Rock.Data.RockContext(); LocationService locationService = new LocationService(rockContext); var addresses = locationService.Queryable() .Where(l => ( (l.IsGeoPointLocked == null || l.IsGeoPointLocked == false) && // don't ever try locked address (l.IsActive == true && l.Street1 != null && l.PostalCode != null) && // or incomplete addresses ( (l.GeocodedDateTime == null && (l.GeocodeAttemptedDateTime == null || l.GeocodeAttemptedDateTime < retryDate)) // has not been attempted to be geocoded since retry date || (l.StandardizedDateTime == null && (l.StandardizeAttemptedDateTime == null || l.StandardizeAttemptedDateTime < retryDate)) // has not been attempted to be standardize since retry date ) )) .Take(maxRecords).ToList(); foreach (var address in addresses) { locationService.Verify(address, false); // currently not reverifying rockContext.SaveChanges(); System.Threading.Thread.Sleep(throttlePeriod); } }
/// <summary> /// Gets the new. /// </summary> /// <param name="alphaNumericLength">Length of the alpha numeric.</param> /// <param name="alphaLength">Length of the alpha.</param> /// <param name="numericLength">Length of the numeric.</param> /// <param name="isRandomized">if set to <c>true</c> [is randomized].</param> /// <returns></returns> public static AttendanceCode GetNew(int alphaNumericLength, int alphaLength, int numericLength, bool isRandomized) { lock ( _obj ) { using (var rockContext = new Rock.Data.RockContext()) { var service = new AttendanceCodeService(rockContext); DateTime today = RockDateTime.Today; if (_todaysCodes == null || !_today.HasValue || !_today.Value.Equals(today)) { _today = today; DateTime tomorrow = today.AddDays(1); _todaysCodes = service.Queryable().AsNoTracking() .Where(c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow) .Select(c => c.Code) .ToList(); } // Find a good alphanumeric code prefix string alphaNumericCode = string.Empty; if (alphaNumericLength > 0 || alphaLength > 0) { alphaNumericCode = (alphaNumericLength > 0 ? GenerateRandomCode(alphaNumericLength) : string.Empty) + (alphaLength > 0 ? GenerateRandomAlphaCode(alphaLength) : string.Empty); while (noGood.Any(s => alphaNumericCode.Contains(s)) || _todaysCodes.Contains(alphaNumericCode)) { alphaNumericCode = (alphaNumericLength > 0 ? GenerateRandomCode(alphaNumericLength) : string.Empty) + (alphaLength > 0 ? GenerateRandomAlphaCode(alphaLength) : string.Empty); } } string numericCode = string.Empty; if (numericLength > 0) { int codeLen = alphaNumericLength + alphaLength + numericLength; var lastCode = _todaysCodes.Where(c => c.Length == codeLen).OrderBy(c => c.Substring(alphaNumericLength + alphaLength)).LastOrDefault(); numericCode = GetNextNumericCodeAsString(alphaNumericLength, alphaLength, numericLength, isRandomized, lastCode); } string code = alphaNumericCode + numericCode; _todaysCodes.Add(code); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add(attendanceCode); rockContext.SaveChanges(); return(attendanceCode); } } }
/// <summary> /// Cleanups the temporary binary files. /// </summary> private void CleanupTemporaryBinaryFiles() { var binaryFileRockContext = new Rock.Data.RockContext(); // clean out any temporary binary files BinaryFileService binaryFileService = new BinaryFileService(binaryFileRockContext); foreach (var binaryFile in binaryFileService.Queryable().Where(bf => bf.IsTemporary == true).ToList()) { if (binaryFile.ModifiedDateTime < RockDateTime.Now.AddDays(-1)) { binaryFileService.Delete(binaryFile); binaryFileRockContext.SaveChanges(); } } }
public IHttpActionResult Login([FromBody] LoginParameters loginParameters, Guid?personalDeviceGuid = null) { var site = MobileHelper.GetCurrentApplicationSite(); if (site == null) { return(StatusCode(System.Net.HttpStatusCode.Unauthorized)); } // // Use the existing AuthController.IsLoginValid method for actual authorization check. Throws exception if not authorized. // if (!AuthController.IsLoginValid(loginParameters, out var errorMessage, out var userName)) { var errorResponse = ControllerContext.Request.CreateErrorResponse(System.Net.HttpStatusCode.Unauthorized, errorMessage); throw new HttpResponseException(errorResponse); } // // Find the user and translate to a mobile person. // using (var rockContext = new Rock.Data.RockContext()) { var userLoginService = new UserLoginService(rockContext); var userLogin = userLoginService.GetByUserName(loginParameters.Username); if (personalDeviceGuid.HasValue) { var personalDevice = new PersonalDeviceService(rockContext).Get(personalDeviceGuid.Value); if (personalDevice != null && personalDevice.PersonAliasId != userLogin.Person.PrimaryAliasId) { personalDevice.PersonAliasId = userLogin.Person.PrimaryAliasId; } } userLogin.LastLoginDateTime = RockDateTime.Now; rockContext.SaveChanges(); var mobilePerson = MobileHelper.GetMobilePerson(userLogin.Person, site); mobilePerson.AuthToken = MobileHelper.GetAuthenticationToken(loginParameters.Username); return(Ok(mobilePerson)); } }
/// <summary> /// Job that updates the JobPulse setting with the current date/time. /// This will allow us to notify an admin if the jobs stop running. /// /// Called by the <see cref="IScheduler" /> when a /// <see cref="ITrigger" /> fires that is associated with /// the <see cref="IJob" />. /// </summary> public virtual void Execute(IJobExecutionContext context) { // get the job map JobDataMap dataMap = context.JobDetail.JobDataMap; int maxRecords = dataMap.GetString("MaxRecordsPerRun").AsIntegerOrNull() ?? 1000; int throttlePeriod = dataMap.GetString("ThrottlePeriod").AsIntegerOrNull() ?? 500; int retryPeriod = dataMap.GetString("RetryPeriod").AsIntegerOrNull() ?? 200; DateTime retryDate = DateTime.Now.Subtract(new TimeSpan(retryPeriod, 0, 0, 0)); var rockContext = new Rock.Data.RockContext(); LocationService locationService = new LocationService(rockContext); var addresses = locationService.Queryable() .Where(l => ( (l.IsGeoPointLocked == null || l.IsGeoPointLocked == false) &&// don't ever try locked address l.IsActive == true && l.Street1 != null && l.Street1 != string.Empty && l.City != null && l.City != string.Empty && ( (l.GeocodedDateTime == null && (l.GeocodeAttemptedDateTime == null || l.GeocodeAttemptedDateTime < retryDate)) || // has not been attempted to be geocoded since retry date (l.StandardizedDateTime == null && (l.StandardizeAttemptedDateTime == null || l.StandardizeAttemptedDateTime < retryDate)) // has not been attempted to be standardize since retry date ) )) .Take(maxRecords).ToList(); int attempts = 0; int successes = 0; foreach (var address in addresses) { attempts++; if (locationService.Verify(address, true)) { successes++; } rockContext.SaveChanges(); System.Threading.Tasks.Task.Delay(throttlePeriod).Wait(); } context.Result = string.Format("{0:N0} address verifications attempted; {1:N0} successfully verified", attempts, successes); }
/// <summary> /// Execute method to write transaction to the database. /// </summary> public void Execute() { // store the view to the database if the viewer is NOT the target (don't track looking at your own record) if (ViewerPersonAliasId != TargetPersonAliasId) { var pvRecord = new PersonViewed(); pvRecord.TargetPersonAliasId = TargetPersonAliasId; pvRecord.ViewerPersonAliasId = ViewerPersonAliasId; pvRecord.ViewDateTime = DateTimeViewed; pvRecord.IpAddress = IPAddress; pvRecord.Source = Source; using (var rockContext = new Rock.Data.RockContext()) { var pvService = new PersonViewedService(rockContext); pvService.Add(pvRecord); rockContext.SaveChanges(); } } }
public IHttpActionResult Login([FromBody] LoginParameters loginParameters, Guid?personalDeviceGuid = null) { var authController = new AuthController(); var site = MobileHelper.GetCurrentApplicationSite(); if (site == null) { return(StatusCode(System.Net.HttpStatusCode.Unauthorized)); } // // Chain to the existing login method for actual authorization check. // Throws exception if not authorized. // authController.Login(loginParameters); // // Find the user and translate to a mobile person. // using (var rockContext = new Rock.Data.RockContext()) { var userLoginService = new UserLoginService(rockContext); var userLogin = userLoginService.GetByUserName(loginParameters.Username); if (personalDeviceGuid.HasValue) { var personalDevice = new PersonalDeviceService(rockContext).Get(personalDeviceGuid.Value); if (personalDevice != null && personalDevice.PersonAliasId != userLogin.Person.PrimaryAliasId) { personalDevice.PersonAliasId = userLogin.Person.PrimaryAliasId; rockContext.SaveChanges(); } } var mobilePerson = MobileHelper.GetMobilePerson(userLogin.Person, site); mobilePerson.AuthToken = MobileHelper.GetAuthenticationToken(loginParameters.Username); return(Ok(mobilePerson)); } }
/// <summary> /// Saves the user preferences. /// </summary> private void SaveUserPreferences() { RockBlock rockBlock = this.RockBlock(); if (rockBlock != null) { string keyPrefix = string.Format("grid-filter-{0}-", rockBlock.BlockId); foreach (var userPreference in _userPreferences) { string keyPrefixUserPreferenceKey = string.Format("{0}{1}|", keyPrefix, userPreference.Key); string key = string.Format("{0}{1}", keyPrefixUserPreferenceKey, userPreference.Name); // No duplicate user preference key values before the '|' are allowed. // This search for any keys that match before the '|' but mismatch after '|' and delete it before writing the user preference. int?personEntityTypeId = EntityTypeCache.Get(Person.USER_VALUE_ENTITY).Id; using (var rockContext = new Rock.Data.RockContext()) { var attributeService = new Model.AttributeService(rockContext); var attributes = attributeService .Queryable() .Where(a => a.EntityTypeId == personEntityTypeId) .Where(a => a.Key.StartsWith(keyPrefixUserPreferenceKey)) .Where(a => a.Key != key); if (attributes.Count() != 0) { foreach (var attribute in attributes) { rockBlock.DeleteUserPreference(attribute.Key); } } rockContext.SaveChanges(); } rockBlock.SetUserPreference(key, userPreference.Value); } } }
/// <summary> /// Cleans up temporary registrations. /// </summary> private int CleanUpTemporaryRegistrations() { var registrationRockContext = new Rock.Data.RockContext(); int totalRowsDeleted = 0; // clean out any temporary registrations RegistrationService registrationService = new RegistrationService(registrationRockContext); foreach (var registration in registrationService.Queryable().Where(bf => bf.IsTemporary == true).ToList()) { if (registration.ModifiedDateTime < RockDateTime.Now.AddHours(-1)) { string errorMessage; if (registrationService.CanDelete(registration, out errorMessage)) { registrationService.Delete(registration); registrationRockContext.SaveChanges(); totalRowsDeleted++; } } } return(totalRowsDeleted); }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode"/> /// </summary> /// <param name="codeLength">A <see cref="System.Int32"/> representing the length of the (security) code.</param> /// <returns>A new <see cref="Rock.Model.AttendanceCode"/></returns> public static AttendanceCode GetNew( int codeLength = 3 ) { lock ( _obj ) { using ( var rockContext = new Rock.Data.RockContext() ) { var service = new AttendanceCodeService( rockContext ); DateTime today = RockDateTime.Today; if ( _todaysCodes == null || !_today.HasValue || !_today.Value.Equals( today ) ) { _today = today; DateTime tomorrow = today.AddDays( 1 ); _todaysCodes = service.Queryable().AsNoTracking() .Where( c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow ) .Select( c => c.Code ) .ToList(); } // Find a good unique code for today string code = GenerateRandomCode( codeLength ); while ( noGood.Any( s => s == code ) || _todaysCodes.Any( c => c == code ) ) { code = GenerateRandomCode( codeLength ); } _todaysCodes.Add( code ); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add( attendanceCode ); rockContext.SaveChanges(); return attendanceCode; } } }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode"/> comprised of random alpha numeric characters. /// </summary> /// <param name="codeLength">A <see cref="System.Int32"/> representing the length of the (security) code.</param> /// <returns>A new <see cref="Rock.Model.AttendanceCode"/></returns> public static AttendanceCode GetNew(int codeLength = 3) { lock ( _obj ) { using (var rockContext = new Rock.Data.RockContext()) { var service = new AttendanceCodeService(rockContext); DateTime today = RockDateTime.Today; if (_todaysCodes == null || !_today.HasValue || !_today.Value.Equals(today)) { _today = today; DateTime tomorrow = today.AddDays(1); _todaysCodes = service.Queryable().AsNoTracking() .Where(c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow) .Select(c => c.Code) .ToList(); } // Find a good unique code for today string code = GenerateRandomCode(codeLength); while (noGood.Any(s => s == code) || _todaysCodes.Any(c => c == code)) { code = GenerateRandomCode(codeLength); } _todaysCodes.Add(code); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add(attendanceCode); rockContext.SaveChanges(); return(attendanceCode); } } }
public HttpResponseMessage ConfirmAccount([FromBody] string confirmationCode) { OAuthContext oAuthContext = new OAuthContext(); ClientService clientService = new ClientService(oAuthContext); var clientId = HttpContext.Current.User.Identity.Name; Client oAuthClient = clientService.GetByApiKey(clientId.AsGuid()); if (oAuthClient.Active) { // Load the User Login that has the confirmation code and mark it as confirmed. var rockContext = new Rock.Data.RockContext(); UserLoginService userLoginService = new UserLoginService(rockContext); UserLogin user = userLoginService.GetByConfirmationCode(confirmationCode); if (user == null) { var unconfirmedAccounts = userLoginService.Queryable().Where(ul => ul.IsConfirmed == false).ToList(); user = unconfirmedAccounts.FirstOrDefault(ul => new BigInteger(MD5.Create().ComputeHash(ul.Guid.ToByteArray())).ToString().Right(6) == confirmationCode); } if (user != null) { user.IsConfirmed = true; rockContext.SaveChanges(); return(ControllerContext.Request.CreateResponse(HttpStatusCode.OK, new StandardResponse() { Message = "Account has been confirmed", Result = StandardResponse.ResultCode.Success })); } return(ControllerContext.Request.CreateResponse(HttpStatusCode.InternalServerError, new StandardResponse() { Message = "Error confirming account.", Result = StandardResponse.ResultCode.Error })); } return(ControllerContext.Request.CreateResponse(HttpStatusCode.Forbidden)); }
/// <summary> /// Cleans up temporary registrations. /// </summary> private int CleanUpTemporaryRegistrations() { var registrationRockContext = new Rock.Data.RockContext(); int totalRowsDeleted = 0; // clean out any temporary registrations RegistrationService registrationService = new RegistrationService( registrationRockContext ); foreach ( var registration in registrationService.Queryable().Where( bf => bf.IsTemporary == true ).ToList() ) { if ( registration.ModifiedDateTime < RockDateTime.Now.AddHours( -1 ) ) { string errorMessage; if ( registrationService.CanDelete( registration, out errorMessage ) ) { registrationService.Delete( registration ); registrationRockContext.SaveChanges(); totalRowsDeleted++; } } } return totalRowsDeleted; }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode" /> with a specified number of alpha characters followed by /// another specified number of numeric characters. The numeric character sequence will not repeat for "today" so /// ensure that you're using a sufficient numericLength otherwise it will be unable to find a unique number. /// Also note as the issued numeric codes reaches the maximum (from the set of possible), it will take longer and /// longer to find an unused number. /// </summary> /// <param name="alphaLength">A <see cref="System.Int32"/> representing the length of the (alpha) portion of the code.</param> /// <param name="numericLength">A <see cref="System.Int32"/> representing the length of the (digit) portion of the code.</param> /// <param name="isRandomized">A <see cref="System.Boolean"/> that controls whether or not the AttendanceCodes should be generated randomly or in order (starting from the smallest).</param> /// <returns> /// A new <see cref="Rock.Model.AttendanceCode" /> /// </returns> public static AttendanceCode GetNew(int alphaLength = 2, int numericLength = 4, bool isRandomized = true) { lock ( _obj ) { using (var rockContext = new Rock.Data.RockContext()) { var service = new AttendanceCodeService(rockContext); DateTime today = RockDateTime.Today; if (_todaysCodes == null || !_today.HasValue || !_today.Value.Equals(today)) { _today = today; DateTime tomorrow = today.AddDays(1); _todaysCodes = service.Queryable().AsNoTracking() .Where(c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow) .Select(c => c.Code) .ToList(); } // Find a good alpha code string alphaCode = GenerateRandomAlphaCode(alphaLength); while (noGood.Any(s => s == alphaCode)) { alphaCode = GenerateRandomAlphaCode(alphaLength); } // Find a good unique numeric code for today string numericCode = string.Empty; if (isRandomized) { numericCode = GenerateRandomNumericCode(numericLength); while (noGood.Any(s => s == numericCode) || _todaysCodes.Any(c => c.EndsWith(numericCode))) { numericCode = GenerateRandomNumericCode(numericLength); } } else { var lastCode = _todaysCodes.OrderBy(c => c.Substring(alphaLength)).LastOrDefault(); if (lastCode != null) { var maxCode = lastCode.Substring(alphaLength); numericCode = (maxCode.AsInteger() + 1).ToString("D" + numericLength); } else { numericCode = 0.ToString("D" + numericLength); } } string code = alphaCode + numericCode; _todaysCodes.Add(code); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add(attendanceCode); rockContext.SaveChanges(); return(attendanceCode); } } }
/// <summary> /// Recursively logs exception and any children. /// </summary> /// <param name="ex">The <see cref="System.Exception"/> to log.</param> /// <param name="log">The parent <see cref="Rock.Model.ExceptionLog"/> of the exception being logged. This value is nullable.</param> /// <param name="isParent">A <see cref="System.Boolean"/> flag indicating if this Exception is a parent exception. This value is /// <c>true</c> if the exception that is being logged is a parent exception, otherwise <c>false</c>. /// </param> private static void LogExceptions( Exception ex, ExceptionLog log, bool isParent ) { // First, attempt to log exception to the database. try { ExceptionLog exceptionLog; // If this is a recursive call and not the originating exception being logged, // attempt to clone the initial one, and populate it with Exception Type and Message // from the inner exception, while retaining the contextual information from where // the exception originated. if ( !isParent ) { exceptionLog = log.Clone( false ); if ( exceptionLog != null ) { // Populate with inner exception type, message and update whether or not there is another inner exception. exceptionLog.ExceptionType = ex.GetType().ToString(); exceptionLog.Description = ex.Message; exceptionLog.Source = ex.Source; exceptionLog.StackTrace = ex.StackTrace; exceptionLog.HasInnerException = ex.InnerException != null; // Ensure EF properly recognizes this as a new record. exceptionLog.Id = 0; exceptionLog.Guid = Guid.NewGuid(); exceptionLog.ParentId = log.Id; } } else { exceptionLog = log; } // The only reason this should happen is if the `log.Clone()` operation failed. Compiler sugar. if ( exceptionLog == null ) { return; } // Write ExceptionLog record to database. var rockContext = new Rock.Data.RockContext(); var exceptionLogService = new ExceptionLogService( rockContext ); exceptionLogService.Add( exceptionLog ); rockContext.SaveChanges(); // Recurse if inner exception is found if ( exceptionLog.HasInnerException.GetValueOrDefault( false ) ) { LogExceptions( ex.InnerException, exceptionLog, false ); } if (ex is AggregateException) { // if an AggregateException occurs, log the exceptions individually var aggregateException = ( ex as AggregateException ); foreach ( var innerException in aggregateException.InnerExceptions ) { LogExceptions( innerException, exceptionLog, false ); } } } catch ( Exception ) { // If logging the exception fails, write the exceptions to a file try { string directory = AppDomain.CurrentDomain.BaseDirectory; directory = Path.Combine( directory, "App_Data", "Logs" ); if ( !Directory.Exists( directory ) ) { Directory.CreateDirectory( directory ); } string filePath = Path.Combine( directory, "RockExceptions.csv" ); string when = RockDateTime.Now.ToString(); while ( ex != null ) { File.AppendAllText( filePath, string.Format( "{0},{1},\"{2}\"\r\n", when, ex.GetType(), ex.Message ) ); ex = ex.InnerException; } } catch { // failed to write to database and also failed to write to log file, so there is nowhere to log this error } } }
/// <summary> /// Execute method to write transaction to the database. /// </summary> public void Execute() { // store the view to the database if the viewer is NOT the target (don't track looking at your own record) if ( ViewerPersonAliasId != TargetPersonAliasId ) { var pvRecord = new PersonViewed(); pvRecord.TargetPersonAliasId = TargetPersonAliasId; pvRecord.ViewerPersonAliasId = ViewerPersonAliasId; pvRecord.ViewDateTime = DateTimeViewed; pvRecord.IpAddress = IPAddress; pvRecord.Source = Source; var rockContext = new Rock.Data.RockContext(); var pvService = new PersonViewedService( rockContext ); pvService.Add( pvRecord ); rockContext.SaveChanges(); } }
/// <summary> /// Updates the scheduled jobs. /// </summary> /// <param name="context">The context.</param> private void UpdateScheduledJobs(IJobExecutionContext context) { var scheduler = context.Scheduler; var rockContext = new Rock.Data.RockContext(); ServiceJobService jobService = new ServiceJobService(rockContext); List <ServiceJob> activeJobList = jobService.GetActiveJobs().ToList(); List <Quartz.JobKey> scheduledQuartzJobs = scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupStartsWith(string.Empty)).ToList(); // delete any jobs that are no longer exist (are are not set to active) in the database var quartsJobsToDelete = scheduledQuartzJobs.Where(a => !activeJobList.Any(j => j.Guid.Equals(a.Name.AsGuid()))); foreach (JobKey jobKey in quartsJobsToDelete) { scheduler.DeleteJob(jobKey); } // add any jobs that are not yet scheduled var newActiveJobs = activeJobList.Where(a => !scheduledQuartzJobs.Any(q => q.Name.AsGuid().Equals(a.Guid))); foreach (Rock.Model.ServiceJob job in newActiveJobs) { try { IJobDetail jobDetail = jobService.BuildQuartzJob(job); ITrigger jobTrigger = jobService.BuildQuartzTrigger(job); scheduler.ScheduleJob(jobDetail, jobTrigger); } catch (Exception ex) { // create a friendly error message string message = string.Format("Error loading the job: {0}. Ensure that the correct version of the job's assembly ({1}.dll) in the websites App_Code directory. \n\n\n\n{2}", job.Name, job.Assembly, ex.Message); job.LastStatusMessage = message; job.LastStatus = "Error Loading Job"; } } rockContext.SaveChanges(); // reload the jobs in case any where added/removed scheduledQuartzJobs = scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupStartsWith(string.Empty)).ToList(); // update schedule if the schedule has changed foreach (var jobKey in scheduledQuartzJobs) { var jobCronTrigger = scheduler.GetTriggersOfJob(jobKey).OfType <ICronTrigger>().FirstOrDefault(); if (jobCronTrigger != null) { var activeJob = activeJobList.FirstOrDefault(a => a.Guid.Equals(jobKey.Name.AsGuid())); if (activeJob != null) { bool rescheduleJob = false; // fix up the schedule if it has changed if (activeJob.CronExpression != jobCronTrigger.CronExpressionString) { rescheduleJob = true; } // update the job detail if it has changed var scheduledJobDetail = scheduler.GetJobDetail(jobKey); var jobDetail = jobService.BuildQuartzJob(activeJob); if (scheduledJobDetail != null && jobDetail != null) { if (scheduledJobDetail.JobType != jobDetail.JobType) { rescheduleJob = true; } if (scheduledJobDetail.JobDataMap.ToJson() != jobDetail.JobDataMap.ToJson()) { rescheduleJob = true; } } if (rescheduleJob) { ITrigger newJobTrigger = jobService.BuildQuartzTrigger(activeJob); scheduler.DeleteJob(jobKey); scheduler.ScheduleJob(jobDetail, newJobTrigger); } } } } }
/// <summary> /// Gets the new. /// </summary> /// <param name="alphaNumericLength">Length of the alpha numeric.</param> /// <param name="alphaLength">Length of the alpha.</param> /// <param name="numericLength">Length of the numeric.</param> /// <param name="isRandomized">if set to <c>true</c> [is randomized].</param> /// <returns></returns> public static AttendanceCode GetNew(int alphaNumericLength, int alphaLength, int numericLength, bool isRandomized) { lock ( _obj ) { using (var rockContext = new Rock.Data.RockContext()) { var service = new AttendanceCodeService(rockContext); DateTime today = RockDateTime.Today; if (_todaysCodes == null || !_today.HasValue || !_today.Value.Equals(today)) { _today = today; DateTime tomorrow = today.AddDays(1); _todaysCodes = new HashSet <string>(service.Queryable().AsNoTracking() .Where(c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow) .Select(c => c.Code) .ToList()); } // Find a good alphanumeric code prefix string alphaNumericCode = string.Empty; int attempts = 0; if (alphaNumericLength > 0 || alphaLength > 0) { alphaNumericCode = (alphaNumericLength > 0 ? GenerateRandomCode(alphaNumericLength) : string.Empty) + (alphaLength > 0 ? GenerateRandomAlphaCode(alphaLength) : string.Empty); while (noGood.Any(s => alphaNumericCode.Contains(s)) || _todaysCodes.Contains(alphaNumericCode)) { attempts++; // We're only going to attempt this 1 million times... // Interestingly, even when this code approaches the maximum number of possible combinations // it still typically takes less than 5000 attempts. However, if the number of // attempts jumps over 10,000 there is almost certainly a problem with someone's // check-in code configuration so we're going to stop after a million attempts. if (attempts > 1000000) { throw new TimeoutException("Too many attempts to create a unique attendance code. There is almost certainly a check-in system 'Security Code Length' configuration problem."); } alphaNumericCode = (alphaNumericLength > 0 ? GenerateRandomCode(alphaNumericLength) : string.Empty) + (alphaLength > 0 ? GenerateRandomAlphaCode(alphaLength) : string.Empty); } } string numericCode = string.Empty; if (numericLength > 0) { int codeLen = alphaNumericLength + alphaLength + numericLength; var lastCode = _todaysCodes.Where(c => c.Length == codeLen).OrderBy(c => c.Substring(alphaNumericLength + alphaLength)).LastOrDefault(); numericCode = GetNextNumericCodeAsString(alphaNumericLength, alphaLength, numericLength, isRandomized, lastCode); } string code = alphaNumericCode + numericCode; _todaysCodes.Add(code); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add(attendanceCode); rockContext.SaveChanges(); return(attendanceCode); } } }
/// <summary> /// Updates the scheduled jobs. /// </summary> /// <param name="context">The context.</param> private void UpdateScheduledJobs( IJobExecutionContext context ) { var scheduler = context.Scheduler; int jobsDeleted = 0; int jobsScheduleUpdated = 0; var rockContext = new Rock.Data.RockContext(); ServiceJobService jobService = new ServiceJobService( rockContext ); List<ServiceJob> activeJobList = jobService.GetActiveJobs().ToList(); List<Quartz.JobKey> scheduledQuartzJobs = scheduler.GetJobKeys( GroupMatcher<JobKey>.GroupStartsWith( string.Empty ) ).ToList(); // delete any jobs that are no longer exist (are are not set to active) in the database var quartsJobsToDelete = scheduledQuartzJobs.Where( a => !activeJobList.Any( j => j.Guid.Equals( a.Name.AsGuid() ) ) ); foreach ( JobKey jobKey in quartsJobsToDelete ) { scheduler.DeleteJob( jobKey ); jobsDeleted++; } // add any jobs that are not yet scheduled var newActiveJobs = activeJobList.Where( a => !scheduledQuartzJobs.Any( q => q.Name.AsGuid().Equals( a.Guid ) ) ); foreach ( Rock.Model.ServiceJob job in newActiveJobs ) { const string errorSchedulingStatus = "Error scheduling Job"; try { IJobDetail jobDetail = jobService.BuildQuartzJob( job ); ITrigger jobTrigger = jobService.BuildQuartzTrigger( job ); scheduler.ScheduleJob( jobDetail, jobTrigger ); jobsScheduleUpdated++; if ( job.LastStatus == errorSchedulingStatus ) { job.LastStatusMessage = string.Empty; job.LastStatus = string.Empty; rockContext.SaveChanges(); } } catch ( Exception ex ) { ExceptionLogService.LogException( ex, null ); // create a friendly error message string message = string.Format( "Error scheduling the job: {0}.\n\n{2}", job.Name, job.Assembly, ex.Message ); job.LastStatusMessage = message; job.LastStatus = errorSchedulingStatus; } } rockContext.SaveChanges(); // reload the jobs in case any where added/removed scheduledQuartzJobs = scheduler.GetJobKeys( GroupMatcher<JobKey>.GroupStartsWith( string.Empty ) ).ToList(); // update schedule if the schedule has changed foreach ( var jobKey in scheduledQuartzJobs ) { var jobCronTrigger = scheduler.GetTriggersOfJob( jobKey ).OfType<ICronTrigger>().FirstOrDefault(); if ( jobCronTrigger != null ) { var activeJob = activeJobList.FirstOrDefault( a => a.Guid.Equals( jobKey.Name.AsGuid() ) ); if ( activeJob != null ) { bool rescheduleJob = false; // fix up the schedule if it has changed if ( activeJob.CronExpression != jobCronTrigger.CronExpressionString ) { rescheduleJob = true; } // update the job detail if it has changed var scheduledJobDetail = scheduler.GetJobDetail( jobKey ); var jobDetail = jobService.BuildQuartzJob( activeJob ); if ( scheduledJobDetail != null && jobDetail != null ) { if ( scheduledJobDetail.JobType != jobDetail.JobType ) { rescheduleJob = true; } if ( scheduledJobDetail.JobDataMap.ToJson() != jobDetail.JobDataMap.ToJson() ) { rescheduleJob = true; } } if ( rescheduleJob ) { const string errorReschedulingStatus = "Error re-scheduling Job"; try { ITrigger newJobTrigger = jobService.BuildQuartzTrigger( activeJob ); bool deletedSuccessfully = scheduler.DeleteJob( jobKey ); scheduler.ScheduleJob( jobDetail, newJobTrigger ); jobsScheduleUpdated++; if ( activeJob.LastStatus == errorReschedulingStatus ) { activeJob.LastStatusMessage = string.Empty; activeJob.LastStatus = string.Empty; rockContext.SaveChanges(); } } catch ( Exception ex ) { ExceptionLogService.LogException( ex, null ); // create a friendly error message string message = string.Format( "Error re-scheduling the job: {0}.\n\n{2}", activeJob.Name, activeJob.Assembly, ex.Message ); activeJob.LastStatusMessage = message; activeJob.LastStatus = errorReschedulingStatus; } } } } } context.Result = string.Empty; if ( jobsDeleted > 0 ) { context.Result += string.Format( "Deleted {0} job schedule(s)", jobsDeleted ); } if ( jobsScheduleUpdated > 0 ) { context.Result += ( string.IsNullOrEmpty( context.Result as string ) ? "" : " and " ) + string.Format( "Updated {0} schedule(s)", jobsScheduleUpdated ); } }
public HttpResponseMessage CreateAccount(Account account) { OAuthContext oAuthContext = new OAuthContext(); ClientService clientService = new ClientService(oAuthContext); var clientId = HttpContext.Current.User.Identity.Name; Client oAuthClient = clientService.GetByApiKey(clientId.AsGuid()); if (oAuthClient.Active) { var rockContext = new Rock.Data.RockContext(); PersonService personService = new PersonService(rockContext); UserLoginService userLoginService = new UserLoginService(rockContext); // Validate the Model if (!string.IsNullOrEmpty(account.Username)) { // Make sure the username is unique UserLogin user = userLoginService.GetByUserName(account.Username); if (user != null) { ModelState.AddModelError("Account.Username", "Username already exists"); } // Make sure the password is valid if (!UserLoginService.IsPasswordValid(account.Password)) { ModelState.AddModelError("Account.Password", UserLoginService.FriendlyPasswordRules()); } // Make sure this person meets the minimum age requirement var birthday = account.Birthdate ?? Rock.RockDateTime.Today; if (RockDateTime.Today.AddYears(MINIMUM_AGE * -1) < birthday) { ModelState.AddModelError("Account.Birthdate", string.Format("We are sorry, you must be at least {0} years old to create an account.", MINIMUM_AGE)); } } if (!ModelState.IsValid) { return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState)); } // Try to match the person var matchPerson = personService.GetByMatch(account.FirstName, account.LastName, account.Birthdate, account.EmailAddress, account.MobileNumber, null, null); bool confirmed = false; Person person = new Person(); if (matchPerson != null && matchPerson.Count() == 1) { var mobilePhone = matchPerson.First().PhoneNumbers.Where(pn => pn.NumberTypeValueId == DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_PHONE_TYPE_MOBILE.AsGuid()).Id).FirstOrDefault(); // The emails MUST match for security if (matchPerson.First().Email == account.EmailAddress && (mobilePhone == null || mobilePhone.Number.Right(10) == account.MobileNumber.Right(10))) { person = matchPerson.First(); // If they don't have a current mobile phone, go ahead and set it if (mobilePhone == null) { string cleanNumber = PhoneNumber.CleanNumber(account.MobileNumber); var phoneNumber = new PhoneNumber { NumberTypeValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_PHONE_TYPE_MOBILE.AsGuid()).Id }; person.PhoneNumbers.Add(phoneNumber); phoneNumber.CountryCode = cleanNumber.Length > 10 ? cleanNumber.Left(10 - cleanNumber.Length) : PhoneNumber.DefaultCountryCode(); phoneNumber.Number = cleanNumber.Right(10); phoneNumber.IsMessagingEnabled = true; } // Make sure the gender matches person.Gender = account.Gender; confirmed = true; } } // If we don't have a match, create a new web prospect if (!confirmed) { DefinedValueCache dvcConnectionStatus = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_CONNECTION_STATUS_WEB_PROSPECT.AsGuid()); DefinedValueCache dvcRecordStatus = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_PENDING.AsGuid()); person.FirstName = account.FirstName; person.LastName = account.LastName; person.NickName = account.NickName; person.Email = account.EmailAddress; person.IsEmailActive = true; person.EmailPreference = EmailPreference.EmailAllowed; person.RecordTypeValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid()).Id; if (dvcConnectionStatus != null) { person.ConnectionStatusValueId = dvcConnectionStatus.Id; } if (dvcRecordStatus != null) { person.RecordStatusValueId = dvcRecordStatus.Id; } person.Gender = account.Gender; var birthday = account.Birthdate; if (birthday.HasValue) { person.BirthMonth = birthday.Value.Month; person.BirthDay = birthday.Value.Day; if (birthday.Value.Year != DateTime.MinValue.Year) { person.BirthYear = birthday.Value.Year; } } if (!string.IsNullOrWhiteSpace(account.MobileNumber)) { string cleanNumber = PhoneNumber.CleanNumber(account.MobileNumber); var phoneNumber = new PhoneNumber { NumberTypeValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_PHONE_TYPE_MOBILE.AsGuid()).Id }; person.PhoneNumbers.Add(phoneNumber); phoneNumber.CountryCode = cleanNumber.Length > 10 ? cleanNumber.Left(10 - cleanNumber.Length) : PhoneNumber.DefaultCountryCode(); phoneNumber.Number = cleanNumber.Right(10); phoneNumber.IsMessagingEnabled = true; } PersonService.SaveNewPerson(person, rockContext); } UserLogin userLogin = null; if (!string.IsNullOrWhiteSpace(account.Username) && UserLoginService.IsPasswordValid(account.Password)) { // Create the user login (only require confirmation if we didn't match the person) userLogin = UserLoginService.Create( rockContext, person, AuthenticationServiceType.Internal, EntityTypeCache.Get(Rock.SystemGuid.EntityType.AUTHENTICATION_DATABASE.AsGuid()).Id, account.Username, account.Password, confirmed); } else if (!string.IsNullOrWhiteSpace(account.EmailAddress) && !confirmed) { userLogin = userLoginService.Queryable() .Where(u => u.UserName == ("SMS_" + person.Id.ToString())) .FirstOrDefault(); // Create an unconfirmed SMS user login if does not exist if (userLogin == null) { var entityTypeId = EntityTypeCache.Get("Rock.Security.ExternalAuthentication.SMSAuthentication").Id; userLogin = new UserLogin() { UserName = "******" + person.Id.ToString(), EntityTypeId = entityTypeId, IsConfirmed = false, PersonId = person.Id }; userLoginService.Add(userLogin); } } // Send an email to confirm the account. if (userLogin != null && userLogin.IsConfirmed != true) { // For mobile we will make a custom/short confirmation code var mobileConfirmationCode = new BigInteger(MD5.Create().ComputeHash(userLogin.Guid.ToByteArray())).ToString().Right(6); var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null, person); mergeFields.Add("MobileConfirmationCode", mobileConfirmationCode); mergeFields.Add("ConfirmAccountUrl", GlobalAttributesCache.Get().GetValue("PublicApplicationRoot").EnsureTrailingForwardslash() + "ConfirmAccount"); mergeFields.Add("Person", userLogin.Person); mergeFields.Add("User", userLogin); var recipients = new List <RockEmailMessageRecipient>(); recipients.Add(new RockEmailMessageRecipient(userLogin.Person, mergeFields)); var message = new RockEmailMessage(Rock.SystemGuid.SystemCommunication.SECURITY_CONFIRM_ACCOUNT.AsGuid()); message.SetRecipients(recipients); message.AppRoot = GlobalAttributesCache.Get().GetValue("PublicApplicationRoot").EnsureTrailingForwardslash(); message.CreateCommunicationRecord = false; message.Send(); } rockContext.SaveChanges(); return(ControllerContext.Request.CreateResponse(HttpStatusCode.OK, new StandardResponse() { Message = string.Format("Account has been created.{0}", confirmed ? "" : " An email has been sent to confirm the email address."), Result = StandardResponse.ResultCode.Success } )); } return(ControllerContext.Request.CreateResponse(HttpStatusCode.Forbidden)); }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode" />. The code will contain the specified number of alphanumeric characters, /// followed by the alpha characters and then the specified number of numeric characters. The character sequence will not repeat for "today". /// Also the numeric character sequence will not repeat for "today". In both cases ensure that you're using a sufficient length for each /// otherwise there will not be enough possible codes. /// Also note as the issued numeric codes reaches the maximum (from the set of possible), it will take longer and /// longer to find an unused number. So specifing a larger number of characters then needed will increase performance. /// </summary> /// <param name="alphaNumericLength">A <see cref="System.Int32"/> representing the length for a mixed alphanumberic code.</param> /// <param name="alphaLength">A <see cref="System.Int32"/> representing the length of the (alpha) portion of the code.</param> /// <param name="numericLength">A <see cref="System.Int32"/> representing the length of the (digit) portion of the code.</param> /// <param name="isRandomized">A <see cref="System.Boolean"/> that controls whether or not the AttendanceCodes should be generated randomly or in order (starting from the smallest). Only effect the numeric code.</param> /// <returns></returns> public static AttendanceCode GetNew(int alphaNumericLength, int alphaLength, int numericLength, bool isRandomized) { lock ( _obj ) { using (var rockContext = new Rock.Data.RockContext()) { var service = new AttendanceCodeService(rockContext); DateTime today = RockDateTime.Today; if (_todaysUsedCodes == null || !_todaysDate.HasValue || !_todaysDate.Value.Equals(today)) { _todaysDate = today; DateTime tomorrow = today.AddDays(1); _todaysUsedCodes = new HashSet <string>(service.Queryable().AsNoTracking().Where(c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow).Select(c => c.Code).ToList()); } string alphaNumericCode = string.Empty; string alphaCode = string.Empty; string numericCode = string.Empty; string code = string.Empty; string lastCode = string.Empty; for (int attempts = 0; attempts <= _maxAttempts; attempts++) { if (attempts == _maxAttempts) { throw new TimeoutException("Too many attempts to create a unique attendance code. There is almost certainly a check-in system 'Security Code Length' configuration problem."); } if (alphaNumericLength > 0) { alphaNumericCode = GenerateRandomCode(alphaNumericLength); } if (alphaLength > 0) { alphaCode = GenerateRandomAlphaCode(alphaLength); } if (numericLength > 0) { int codeLen = alphaNumericLength + alphaLength + numericLength; if (lastCode.IsNullOrWhiteSpace()) { lastCode = _todaysUsedCodes.Where(c => c.Length == codeLen).OrderBy(c => c.Substring(alphaNumericLength + alphaLength)).LastOrDefault(); } numericCode = GetNextNumericCodeAsString(alphaNumericLength, alphaLength, numericLength, isRandomized, lastCode); } code = alphaNumericCode + alphaCode + numericCode; // Check if code is already in use or contains bad unallowed strings. if (noGood.Any(s => code.Contains(s)) || _todaysUsedCodes.Contains(code)) { lastCode = numericCode; alphaNumericCode = string.Empty; alphaCode = string.Empty; numericCode = string.Empty; code = string.Empty; continue; } // When using a clustered environment we need to check the DB to make sure the code hasn't been assigned by another server if (Rock.Utility.Settings.RockInstanceConfig.IsClustered) { if (service.IsCodeAlreadyInUse(code)) { lastCode = numericCode; alphaNumericCode = string.Empty; alphaCode = string.Empty; numericCode = string.Empty; code = string.Empty; continue; } } // If we get to this point the code can be used break; } _todaysUsedCodes.Add(code); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add(attendanceCode); rockContext.SaveChanges(); return(attendanceCode); } } }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode" /> with a specified number of alpha characters followed by /// another specified number of numeric characters. The numeric character sequence will not repeat for "today" so /// ensure that you're using a sufficient numericLength otherwise it will be unable to find a unique number. /// Also note as the issued numeric codes reaches the maximum (from the set of possible), it will take longer and /// longer to find an unused number. /// </summary> /// <param name="alphaLength">A <see cref="System.Int32"/> representing the length of the (alpha) portion of the code.</param> /// <param name="numericLength">A <see cref="System.Int32"/> representing the length of the (digit) portion of the code.</param> /// <param name="isRandomized">A <see cref="System.Boolean"/> that controls whether or not the AttendanceCodes should be generated randomly or in order (starting from the smallest).</param> /// <returns> /// A new <see cref="Rock.Model.AttendanceCode" /> /// </returns> public static AttendanceCode GetNew( int alphaLength = 2, int numericLength = 4, bool isRandomized = true ) { lock ( _obj ) { using ( var rockContext = new Rock.Data.RockContext() ) { var service = new AttendanceCodeService( rockContext ); DateTime today = RockDateTime.Today; if ( _todaysCodes == null || !_today.HasValue || !_today.Value.Equals( today ) ) { _today = today; DateTime tomorrow = today.AddDays( 1 ); _todaysCodes = service.Queryable().AsNoTracking() .Where( c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow ) .Select( c => c.Code ) .ToList(); } // Find a good alpha code string alphaCode = GenerateRandomAlphaCode( alphaLength ); while ( noGood.Any( s => s == alphaCode ) ) { alphaCode = GenerateRandomAlphaCode( alphaLength ); } // Find a good unique numeric code for today string numericCode = string.Empty; if ( isRandomized ) { numericCode = GenerateRandomNumericCode( numericLength ); while ( noGood.Any( s => s == numericCode ) || _todaysCodes.Any( c => c.EndsWith( numericCode ) ) ) { numericCode = GenerateRandomNumericCode( numericLength ); } } else { var lastCode = _todaysCodes.OrderBy( c => c.Substring( alphaLength ) ).LastOrDefault(); if ( lastCode != null ) { var maxCode = lastCode.Substring( alphaLength ); numericCode = ( maxCode.AsInteger() + 1 ).ToString( "D" + numericLength ); } else { numericCode = 0.ToString( "D" + numericLength ); } } string code = alphaCode + numericCode; _todaysCodes.Add( code ); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add( attendanceCode ); rockContext.SaveChanges(); return attendanceCode; } } }
/// <summary> /// Recursively logs exception and any children. /// </summary> /// <param name="ex">The <see cref="System.Exception"/> to log.</param> /// <param name="log">The parent <see cref="Rock.Model.ExceptionLog"/> of the exception being logged. This value is nullable.</param> /// <param name="isParent">A <see cref="System.Boolean"/> flag indicating if this Exception is a parent exception. This value is /// <c>true</c> if the exception that is being logged is a parent exception, otherwise <c>false</c>. /// </param> private static void LogExceptions(Exception ex, ExceptionLog log, bool isParent) { // First, attempt to log exception to the database. try { ExceptionLog exceptionLog; // If this is a recursive call and not the originating exception being logged, // attempt to clone the initial one, and populate it with Exception Type and Message // from the inner exception, while retaining the contextual information from where // the exception originated. if (!isParent) { exceptionLog = log.Clone(false); if (exceptionLog != null) { // Populate with inner exception type, message and update whether or not there is another inner exception. exceptionLog.ExceptionType = ex.GetType().ToString(); exceptionLog.Description = ex.Message; exceptionLog.Source = ex.Source; exceptionLog.StackTrace = ex.StackTrace; exceptionLog.HasInnerException = ex.InnerException != null; // Ensure EF properly recognizes this as a new record. exceptionLog.Id = 0; exceptionLog.Guid = Guid.NewGuid(); exceptionLog.ParentId = log.Id; } } else { exceptionLog = log; } // The only reason this should happen is if the `log.Clone()` operation failed. Compiler sugar. if (exceptionLog == null) { return; } // Write ExceptionLog record to database. var rockContext = new Rock.Data.RockContext(); var exceptionLogService = new ExceptionLogService(rockContext); exceptionLogService.Add(exceptionLog); rockContext.SaveChanges(); // Recurse if inner exception is found if (exceptionLog.HasInnerException.GetValueOrDefault(false)) { LogExceptions(ex.InnerException, exceptionLog, false); } } catch (Exception) { // If logging the exception fails, write the exceptions to a file try { string directory = AppDomain.CurrentDomain.BaseDirectory; directory = Path.Combine(directory, "App_Data", "Logs"); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } string filePath = Path.Combine(directory, "RockExceptions.csv"); string when = RockDateTime.Now.ToString(); while (ex != null) { File.AppendAllText(filePath, string.Format("{0},{1},\"{2}\"\r\n", when, ex.GetType(), ex.Message)); ex = ex.InnerException; } } catch { // failed to write to database and also failed to write to log file, so there is nowhere to log this error } } }
/// <summary> /// Cleans up expired entity sets. /// </summary> /// <param name="dataMap">The data map.</param> private int CleanupExpiredEntitySets( JobDataMap dataMap ) { var entitySetRockContext = new Rock.Data.RockContext(); var currentDateTime = RockDateTime.Now; var entitySetService = new EntitySetService( entitySetRockContext ); var qry = entitySetService.Queryable().Where( a => a.ExpireDateTime.HasValue && a.ExpireDateTime < currentDateTime ); int totalRowsDeleted = 0; foreach ( var entitySet in qry.ToList() ) { string deleteWarning; if ( entitySetService.CanDelete( entitySet, out deleteWarning ) ) { // delete in chunks (see http://dba.stackexchange.com/questions/1750/methods-of-speeding-up-a-huge-delete-from-table-with-no-clauses) bool keepDeleting = true; while ( keepDeleting ) { var dbTransaction = entitySetRockContext.Database.BeginTransaction(); try { string sqlCommand = @"DELETE TOP (1000) FROM [EntitySetItem] WHERE [EntitySetId] = @entitySetId"; int rowsDeleted = entitySetRockContext.Database.ExecuteSqlCommand( sqlCommand, new SqlParameter( "entitySetId", entitySet.Id ) ); keepDeleting = rowsDeleted > 0; totalRowsDeleted += rowsDeleted; } finally { dbTransaction.Commit(); } } entitySetService.Delete( entitySet ); entitySetRockContext.SaveChanges(); } } return totalRowsDeleted; }
/// <summary> /// Does cleanup of Person Aliases and Metaphones /// </summary> /// <param name="dataMap">The data map.</param> private void PersonCleanup( JobDataMap dataMap ) { // Add any missing person aliases var personRockContext = new Rock.Data.RockContext(); PersonService personService = new PersonService( personRockContext ); foreach ( var person in personService.Queryable( "Aliases" ) .Where( p => !p.Aliases.Any() ) .Take( 300 ) ) { person.Aliases.Add( new PersonAlias { AliasPersonId = person.Id, AliasPersonGuid = person.Guid } ); } personRockContext.SaveChanges(); // Add any missing metaphones int namesToProcess = dataMap.GetString( "MaxMetaphoneNames" ).AsInteger(); if ( namesToProcess > 0 ) { var firstNameQry = personService.Queryable().Select( p => p.FirstName ).Where( p => p != null ); var nickNameQry = personService.Queryable().Select( p => p.NickName ).Where( p => p != null ); var lastNameQry = personService.Queryable().Select( p => p.LastName ).Where( p => p != null ); var nameQry = firstNameQry.Union( nickNameQry.Union( lastNameQry ) ); var metaphones = personRockContext.Metaphones; var existingNames = metaphones.Select( m => m.Name ).Distinct(); // Get the names that have not yet been processed var namesToUpdate = nameQry .Where( n => !existingNames.Contains( n ) ) .Take( namesToProcess ) .ToList(); foreach ( string name in namesToUpdate ) { string mp1 = string.Empty; string mp2 = string.Empty; Rock.Utility.DoubleMetaphone.doubleMetaphone( name, ref mp1, ref mp2 ); var metaphone = new Metaphone(); metaphone.Name = name; metaphone.Metaphone1 = mp1; metaphone.Metaphone2 = mp2; metaphones.Add( metaphone ); } personRockContext.SaveChanges(); } }
/// <summary> /// Job that updates the JobPulse setting with the current date/time. /// This will allow us to notify an admin if the jobs stop running. /// /// Called by the <see cref="IScheduler" /> when a /// <see cref="ITrigger" /> fires that is associated with /// the <see cref="IJob" />. /// </summary> public virtual void Execute(IJobExecutionContext context) { // get the job map JobDataMap dataMap = context.JobDetail.JobDataMap; int maxRecords = Int32.Parse( dataMap.GetString( "MaxRecordsPerRun" ) ); int throttlePeriod = Int32.Parse( dataMap.GetString( "ThrottlePeriod" ) ); int retryPeriod = Int32.Parse( dataMap.GetString( "RetryPeriod" ) ); DateTime retryDate = DateTime.Now.Subtract(new TimeSpan(retryPeriod, 0, 0, 0)); var rockContext = new Rock.Data.RockContext(); LocationService locationService = new LocationService(rockContext); var addresses = locationService.Queryable() .Where( l => ( ( l.IsGeoPointLocked == null || l.IsGeoPointLocked == false ) &&// don't ever try locked address l.IsActive == true && l.Street1 != null && l.Street1 != "" && l.City != null && l.City != "" && ( ( l.GeocodedDateTime == null && ( l.GeocodeAttemptedDateTime == null || l.GeocodeAttemptedDateTime < retryDate ) ) || // has not been attempted to be geocoded since retry date ( l.StandardizedDateTime == null && ( l.StandardizeAttemptedDateTime == null || l.StandardizeAttemptedDateTime < retryDate ) ) // has not been attempted to be standardize since retry date ) ) ) .Take( maxRecords ).ToList(); int attempts = 0; int successes = 0; foreach ( var address in addresses ) { attempts++; if ( locationService.Verify( address, true ) ) { successes++; } rockContext.SaveChanges(); System.Threading.Thread.Sleep( throttlePeriod ); } context.Result = string.Format( "{0:N0} address verifications attempted; {1:N0} successfully verified", attempts, successes ); }
/// <summary> /// Cleanups the temporary binary files. /// </summary> private void CleanupTemporaryBinaryFiles() { var binaryFileRockContext = new Rock.Data.RockContext(); // clean out any temporary binary files BinaryFileService binaryFileService = new BinaryFileService( binaryFileRockContext ); foreach ( var binaryFile in binaryFileService.Queryable().Where( bf => bf.IsTemporary == true ).ToList() ) { if ( binaryFile.ModifiedDateTime < RockDateTime.Now.AddDays( -1 ) ) { binaryFileService.Delete( binaryFile ); binaryFileRockContext.SaveChanges(); } } }
public IHttpActionResult GetLaunchPacket(string deviceIdentifier = null, bool?notificationsEnabled = null) { var site = MobileHelper.GetCurrentApplicationSite(); var additionalSettings = site?.AdditionalSettings.FromJsonOrNull <AdditionalSiteSettings>(); var rockContext = new Rock.Data.RockContext(); var person = GetPerson(rockContext); var deviceData = Request.GetHeader("X-Rock-DeviceData").FromJsonOrNull <DeviceData>(); if (additionalSettings == null || !additionalSettings.LastDeploymentDate.HasValue) { return(NotFound()); } // Ensure the user login is still active, otherwise log them out. var principal = ControllerContext.Request.GetUserPrincipal(); if (person != null && !principal.Identity.Name.StartsWith("rckipid=")) { var userLogin = new UserLoginService(rockContext).GetByUserName(principal.Identity.Name); if (userLogin?.IsConfirmed != true || userLogin?.IsLockedOut == true) { person = null; } } var launchPacket = new LaunchPacket { RockVersion = Rock.VersionInfo.VersionInfo.GetRockProductVersionNumber(), LatestVersionId = additionalSettings.LastDeploymentVersionId ?? ( int )(additionalSettings.LastDeploymentDate.Value.ToJavascriptMilliseconds() / 1000), IsSiteAdministrator = site.IsAuthorized(Rock.Security.Authorization.EDIT, person) }; if (deviceData.DeviceType == DeviceType.Phone) { launchPacket.LatestVersionSettingsUrl = additionalSettings.PhoneUpdatePackageUrl; } else if (deviceData.DeviceType == DeviceType.Tablet) { launchPacket.LatestVersionSettingsUrl = additionalSettings.TabletUpdatePackageUrl; } else { return(NotFound()); } if (person != null) { //var principal = ControllerContext.Request.GetUserPrincipal(); launchPacket.CurrentPerson = MobileHelper.GetMobilePerson(person, site); launchPacket.CurrentPerson.AuthToken = MobileHelper.GetAuthenticationToken(principal.Identity.Name); UserLoginService.UpdateLastLogin(principal.Identity.Name); } // // Get or create the personal device. // if (deviceIdentifier.IsNotNullOrWhiteSpace()) { var mobileDeviceTypeValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSONAL_DEVICE_TYPE_MOBILE).Id; var personalDeviceService = new PersonalDeviceService(rockContext); var personalDevice = personalDeviceService.Queryable() .Where(a => a.DeviceUniqueIdentifier == deviceIdentifier && a.PersonalDeviceTypeValueId == mobileDeviceTypeValueId && a.SiteId == site.Id) .FirstOrDefault(); if (personalDevice == null) { personalDevice = new PersonalDevice { DeviceUniqueIdentifier = deviceIdentifier, PersonalDeviceTypeValueId = mobileDeviceTypeValueId, SiteId = site.Id, PlatformValueId = deviceData.DevicePlatform.GetDevicePlatformValueId(), PersonAliasId = person?.PrimaryAliasId, NotificationsEnabled = true, Manufacturer = deviceData.Manufacturer, Model = deviceData.Model, Name = deviceData.Name, LastSeenDateTime = RockDateTime.Now }; personalDeviceService.Add(personalDevice); rockContext.SaveChanges(); } else { // A change is determined as one of the following: // 1) A change in Name, Manufacturer, Model, or NotificationsEnabled. // 2) Device not being active. // 3) Not seen in 24 hours. // 4) Signed in with a different person. var hasDeviceChanged = !personalDevice.IsActive || personalDevice.Name != deviceData.Name || personalDevice.Manufacturer != deviceData.Manufacturer || personalDevice.Model != deviceData.Model || personalDevice.NotificationsEnabled != (notificationsEnabled ?? true) || !personalDevice.LastSeenDateTime.HasValue || personalDevice.LastSeenDateTime.Value.AddDays(1) < RockDateTime.Now || (person != null && personalDevice.PersonAliasId != person.PrimaryAliasId); if (hasDeviceChanged) { personalDevice.IsActive = true; personalDevice.Manufacturer = deviceData.Manufacturer; personalDevice.Model = deviceData.Model; personalDevice.Name = deviceData.Name; personalDevice.LastSeenDateTime = RockDateTime.Now; if (notificationsEnabled.HasValue) { personalDevice.NotificationsEnabled = notificationsEnabled.Value; } // Update the person tied to the device, but never blank it out. if (person != null && personalDevice.PersonAliasId != person.PrimaryAliasId) { personalDevice.PersonAliasId = person.PrimaryAliasId; } rockContext.SaveChanges(); } } launchPacket.PersonalDeviceGuid = personalDevice.Guid; } return(Ok(launchPacket)); }
/// <summary> /// Purges the audit log. /// </summary> /// <param name="dataMap">The data map.</param> private void PurgeAuditLog( JobDataMap dataMap ) { // purge audit log int? auditExpireDays = dataMap.GetString( "AuditLogExpirationDays" ).AsIntegerOrNull(); if ( auditExpireDays.HasValue ) { var auditLogRockContext = new Rock.Data.RockContext(); DateTime auditExpireDate = RockDateTime.Now.Add( new TimeSpan( auditExpireDays.Value * -1, 0, 0, 0 ) ); // delete in chunks (see http://dba.stackexchange.com/questions/1750/methods-of-speeding-up-a-huge-delete-from-table-with-no-clauses) bool keepDeleting = true; while ( keepDeleting ) { var dbTransaction = auditLogRockContext.Database.BeginTransaction(); try { int rowsDeleted = auditLogRockContext.Database.ExecuteSqlCommand( @"DELETE TOP (1000) FROM [Audit] WHERE [DateTime] < @auditExpireDate", new SqlParameter( "auditExpireDate", auditExpireDate ) ); keepDeleting = rowsDeleted > 0; } finally { dbTransaction.Commit(); } } auditLogRockContext.SaveChanges(); } }
public IHttpActionResult GetLaunchPacket(string deviceIdentifier = null) { var site = MobileHelper.GetCurrentApplicationSite(); var additionalSettings = site?.AdditionalSettings.FromJsonOrNull <AdditionalSiteSettings>(); var rockContext = new Rock.Data.RockContext(); var person = GetPerson(rockContext); var deviceData = Request.GetHeader("X-Rock-DeviceData").FromJsonOrNull <DeviceData>(); if (additionalSettings == null || !additionalSettings.LastDeploymentDate.HasValue) { return(NotFound()); } var launchPacket = new LaunchPacket { LatestVersionId = ( int )(additionalSettings.LastDeploymentDate.Value.ToJavascriptMilliseconds() / 1000), IsSiteAdministrator = site.IsAuthorized(Authorization.EDIT, person) }; if (deviceData.DeviceType == DeviceType.Phone) { launchPacket.LatestVersionSettingsUrl = additionalSettings.PhoneUpdatePackageUrl; } else if (deviceData.DeviceType == DeviceType.Tablet) { launchPacket.LatestVersionSettingsUrl = additionalSettings.TabletUpdatePackageUrl; } else { return(NotFound()); } if (person != null) { var principal = ControllerContext.Request.GetUserPrincipal(); launchPacket.CurrentPerson = MobileHelper.GetMobilePerson(person, site); launchPacket.CurrentPerson.AuthToken = MobileHelper.GetAuthenticationToken(principal.Identity.Name); } // // Get or create the personal device. // if (deviceIdentifier.IsNotNullOrWhiteSpace()) { var mobileDeviceTypeValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSONAL_DEVICE_TYPE_MOBILE).Id; var personalDeviceService = new PersonalDeviceService(rockContext); var personalDevice = personalDeviceService.Queryable() .AsNoTracking() .Where(a => a.DeviceUniqueIdentifier == deviceIdentifier && a.PersonalDeviceTypeValueId == mobileDeviceTypeValueId) .FirstOrDefault(); if (personalDevice == null) { personalDevice = new PersonalDevice { DeviceUniqueIdentifier = deviceIdentifier, PersonalDeviceTypeValueId = mobileDeviceTypeValueId, PlatformValueId = deviceData.DevicePlatform.GetDevicePlatformValueId(), PersonAliasId = person?.PrimaryAliasId, NotificationsEnabled = true }; personalDeviceService.Add(personalDevice); rockContext.SaveChanges(); } launchPacket.PersonalDeviceGuid = personalDevice.Guid; } return(Ok(launchPacket)); }
/// <summary> /// Job that executes routine Rock cleanup tasks /// /// Called by the <see cref="IScheduler" /> when a /// <see cref="ITrigger" /> fires that is associated with /// the <see cref="IJob" />. /// </summary> public virtual void Execute( IJobExecutionContext context ) { var rockContext = new Rock.Data.RockContext(); // get the job map JobDataMap dataMap = context.JobDetail.JobDataMap; // delete accounts that have not been confirmed in X hours int? userExpireHours = dataMap.GetString( "HoursKeepUnconfirmedAccounts" ).AsIntegerOrNull(); if ( userExpireHours.HasValue ) { DateTime userAccountExpireDate = RockDateTime.Now.Add( new TimeSpan( userExpireHours.Value * -1, 0, 0 ) ); var userLoginService = new UserLoginService(rockContext); foreach ( var user in userLoginService.Queryable().Where( u => u.IsConfirmed == false && ( u.CreatedDateTime ?? DateTime.MinValue ) < userAccountExpireDate ).ToList() ) { userLoginService.Delete( user ); } rockContext.SaveChanges(); } // purge exception log int? exceptionExpireDays = dataMap.GetString( "DaysKeepExceptions" ).AsIntegerOrNull(); if ( exceptionExpireDays.HasValue ) { DateTime exceptionExpireDate = RockDateTime.Now.Add( new TimeSpan( exceptionExpireDays.Value * -1, 0, 0, 0 ) ); ExceptionLogService exceptionLogService = new ExceptionLogService( rockContext ); foreach ( var exception in exceptionLogService.Queryable().Where( e => e.CreatedDateTime.HasValue && e.CreatedDateTime < exceptionExpireDate ).ToList() ) { exceptionLogService.Delete( exception ); } rockContext.SaveChanges(); } // purge audit log int? auditExpireDays = dataMap.GetString( "AuditLogExpirationDays" ).AsIntegerOrNull(); if ( auditExpireDays.HasValue ) { DateTime auditExpireDate = RockDateTime.Now.Add( new TimeSpan( auditExpireDays.Value * -1, 0, 0, 0 ) ); AuditService auditService = new AuditService(rockContext); foreach ( var audit in auditService.Queryable().Where( a => a.DateTime < auditExpireDate ).ToList() ) { auditService.Delete( audit ); } rockContext.SaveChanges(); } // clean the cached file directory // get the attributes string cacheDirectoryPath = dataMap.GetString( "BaseCacheDirectory" ); int? cacheExpirationDays = dataMap.GetString( "DaysKeepCachedFiles" ).AsIntegerOrNull(); if ( cacheExpirationDays.HasValue ) { DateTime cacheExpirationDate = RockDateTime.Now.Add( new TimeSpan( cacheExpirationDays.Value * -1, 0, 0, 0 ) ); // if job is being run by the IIS scheduler and path is not null if ( context.Scheduler.SchedulerName == "RockSchedulerIIS" && !string.IsNullOrEmpty( cacheDirectoryPath ) ) { // get the physical path of the cache directory cacheDirectoryPath = System.Web.Hosting.HostingEnvironment.MapPath( cacheDirectoryPath ); } // if directory is not blank and cache expiration date not in the future if ( !string.IsNullOrEmpty( cacheDirectoryPath ) && cacheExpirationDate <= RockDateTime.Now ) { // Clean cache directory CleanCacheDirectory( cacheDirectoryPath, cacheExpirationDate ); } } // clean out any temporary binary files BinaryFileService binaryFileService = new BinaryFileService(rockContext); foreach ( var binaryFile in binaryFileService.Queryable().Where( bf => bf.IsTemporary == true ).ToList() ) { if ( binaryFile.ModifiedDateTime < RockDateTime.Now.AddDays( -1 ) ) { binaryFileService.Delete( binaryFile ); } } rockContext.SaveChanges(); // Add any missing person aliases PersonService personService = new PersonService(rockContext); foreach ( var person in personService.Queryable( "Aliases" ) .Where( p => !p.Aliases.Any() ) .Take( 300 ) ) { person.Aliases.Add( new PersonAlias { AliasPersonId = person.Id, AliasPersonGuid = person.Guid } ); } rockContext.SaveChanges(); // Add any missing metaphones int namesToProcess = dataMap.GetString( "MaxMetaphoneNames" ).AsInteger(); if ( namesToProcess > 0 ) { var firstNameQry = personService.Queryable().Select( p => p.FirstName ); var nickNameQry = personService.Queryable().Select( p => p.NickName ); var lastNameQry = personService.Queryable().Select( p => p.LastName ); var nameQry = firstNameQry.Union( nickNameQry.Union( lastNameQry ) ); var metaphones = rockContext.Metaphones; var existingNames = metaphones.Select( m => m.Name ).Distinct(); // Get the names that have not yet been processed var namesToUpdate = nameQry .Where( n => !existingNames.Contains( n ) ) .Take( namesToProcess ) .ToList(); foreach ( string name in namesToUpdate ) { string mp1 = string.Empty; string mp2 = string.Empty; Rock.Utility.DoubleMetaphone.doubleMetaphone( name, ref mp1, ref mp2 ); var metaphone = new Metaphone(); metaphone.Name = name; metaphone.Metaphone1 = mp1; metaphone.Metaphone2 = mp2; metaphones.Add( metaphone ); } rockContext.SaveChanges(); } }
/// <summary> /// Updates the scheduled jobs. /// </summary> /// <param name="context">The context.</param> private void UpdateScheduledJobs( IJobExecutionContext context ) { var scheduler = context.Scheduler; var rockContext = new Rock.Data.RockContext(); ServiceJobService jobService = new ServiceJobService( rockContext ); List<ServiceJob> activeJobList = jobService.GetActiveJobs().ToList(); List<Quartz.JobKey> scheduledQuartzJobs = scheduler.GetJobKeys( GroupMatcher<JobKey>.GroupStartsWith( string.Empty ) ).ToList(); // delete any jobs that are no longer exist (are are not set to active) in the database var quartsJobsToDelete = scheduledQuartzJobs.Where( a => !activeJobList.Any( j => j.Guid.Equals( a.Name.AsGuid() ) ) ); foreach ( JobKey jobKey in quartsJobsToDelete ) { scheduler.DeleteJob( jobKey ); } // add any jobs that are not yet scheduled var newActiveJobs = activeJobList.Where( a => !scheduledQuartzJobs.Any( q => q.Name.AsGuid().Equals( a.Guid ) ) ); foreach ( Rock.Model.ServiceJob job in newActiveJobs ) { try { IJobDetail jobDetail = jobService.BuildQuartzJob( job ); ITrigger jobTrigger = jobService.BuildQuartzTrigger( job ); scheduler.ScheduleJob( jobDetail, jobTrigger ); } catch ( Exception ex ) { // create a friendly error message string message = string.Format( "Error loading the job: {0}. Ensure that the correct version of the job's assembly ({1}.dll) in the websites App_Code directory. \n\n\n\n{2}", job.Name, job.Assembly, ex.Message ); job.LastStatusMessage = message; job.LastStatus = "Error Loading Job"; } } rockContext.SaveChanges(); // reload the jobs in case any where added/removed scheduledQuartzJobs = scheduler.GetJobKeys( GroupMatcher<JobKey>.GroupStartsWith( string.Empty ) ).ToList(); // update schedule if the schedule has changed foreach ( var jobKey in scheduledQuartzJobs ) { var jobCronTrigger = scheduler.GetTriggersOfJob( jobKey ).OfType<ICronTrigger>().FirstOrDefault(); if ( jobCronTrigger != null ) { var activeJob = activeJobList.FirstOrDefault( a => a.Guid.Equals( jobKey.Name.AsGuid() ) ); if ( activeJob != null ) { if ( activeJob.CronExpression != jobCronTrigger.CronExpressionString ) { ITrigger newJobTrigger = jobService.BuildQuartzTrigger( activeJob ); scheduler.RescheduleJob( jobCronTrigger.Key, newJobTrigger ); } } } } }
/// <summary> /// Updates the scheduled jobs. /// </summary> /// <param name="context">The context.</param> private void UpdateScheduledJobs(IJobExecutionContext context) { var scheduler = context.Scheduler; int jobsDeleted = 0; int jobsScheduleUpdated = 0; var rockContext = new Rock.Data.RockContext(); ServiceJobService jobService = new ServiceJobService(rockContext); List <ServiceJob> activeJobList = jobService.GetActiveJobs().ToList(); List <Quartz.JobKey> scheduledQuartzJobs = scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupStartsWith(string.Empty)).ToList(); // delete any jobs that are no longer exist (are are not set to active) in the database var quartsJobsToDelete = scheduledQuartzJobs.Where(a => !activeJobList.Any(j => j.Guid.Equals(a.Name.AsGuid()))); foreach (JobKey jobKey in quartsJobsToDelete) { scheduler.DeleteJob(jobKey); jobsDeleted++; } // add any jobs that are not yet scheduled var newActiveJobs = activeJobList.Where(a => !scheduledQuartzJobs.Any(q => q.Name.AsGuid().Equals(a.Guid))); foreach (Rock.Model.ServiceJob job in newActiveJobs) { const string errorSchedulingStatus = "Error scheduling Job"; try { IJobDetail jobDetail = jobService.BuildQuartzJob(job); ITrigger jobTrigger = jobService.BuildQuartzTrigger(job); scheduler.ScheduleJob(jobDetail, jobTrigger); jobsScheduleUpdated++; if (job.LastStatus == errorSchedulingStatus) { job.LastStatusMessage = string.Empty; job.LastStatus = string.Empty; rockContext.SaveChanges(); } } catch (Exception ex) { ExceptionLogService.LogException(ex, null); // create a friendly error message string message = string.Format("Error scheduling the job: {0}.\n\n{2}", job.Name, job.Assembly, ex.Message); job.LastStatusMessage = message; job.LastStatus = errorSchedulingStatus; } } rockContext.SaveChanges(); // reload the jobs in case any where added/removed scheduledQuartzJobs = scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupStartsWith(string.Empty)).ToList(); // update schedule if the schedule has changed foreach (var jobKey in scheduledQuartzJobs) { var jobCronTrigger = scheduler.GetTriggersOfJob(jobKey).OfType <ICronTrigger>().FirstOrDefault(); if (jobCronTrigger != null) { var activeJob = activeJobList.FirstOrDefault(a => a.Guid.Equals(jobKey.Name.AsGuid())); if (activeJob != null) { bool rescheduleJob = false; // fix up the schedule if it has changed if (activeJob.CronExpression != jobCronTrigger.CronExpressionString) { rescheduleJob = true; } // update the job detail if it has changed var scheduledJobDetail = scheduler.GetJobDetail(jobKey); var jobDetail = jobService.BuildQuartzJob(activeJob); if (scheduledJobDetail != null && jobDetail != null) { if (scheduledJobDetail.JobType != jobDetail.JobType) { rescheduleJob = true; } if (scheduledJobDetail.JobDataMap.ToJson() != jobDetail.JobDataMap.ToJson()) { rescheduleJob = true; } } if (rescheduleJob) { const string errorReschedulingStatus = "Error re-scheduling Job"; try { ITrigger newJobTrigger = jobService.BuildQuartzTrigger(activeJob); bool deletedSuccessfully = scheduler.DeleteJob(jobKey); scheduler.ScheduleJob(jobDetail, newJobTrigger); jobsScheduleUpdated++; if (activeJob.LastStatus == errorReschedulingStatus) { activeJob.LastStatusMessage = string.Empty; activeJob.LastStatus = string.Empty; rockContext.SaveChanges(); } } catch (Exception ex) { ExceptionLogService.LogException(ex, null); // create a friendly error message string message = string.Format("Error re-scheduling the job: {0}.\n\n{2}", activeJob.Name, activeJob.Assembly, ex.Message); activeJob.LastStatusMessage = message; activeJob.LastStatus = errorReschedulingStatus; } } } } } context.Result = string.Empty; if (jobsDeleted > 0) { context.Result += string.Format("Deleted {0} job schedule(s)", jobsDeleted); } if (jobsScheduleUpdated > 0) { context.Result += (string.IsNullOrEmpty(context.Result as string) ? "" : " and ") + string.Format("Updated {0} schedule(s)", jobsScheduleUpdated); } }