private BeholdEmailer CreateBeholdEmailerFromConfig(string site) { var tabrep = new TableauRepository( Configurator.GetConfig("tableau_server"), Configurator.GetConfig("repository_pw"), "readonly" ) { logger = this.Logger }; var tabcmd = new Tabcmd( Configurator.GetConfig("tabcmd_program_location"), Configurator.GetConfig("tableau_server"), Configurator.GetConfig("server_admin_username"), Configurator.GetConfig("server_admin_password"), site, Configurator.GetConfig("tabcmd_config_location"), tabrep, this.Logger ); BeholdEmailer tabemailer = new BeholdEmailer(tabcmd, this.CreateSmtpClientFromConfig()); tabemailer.Logger = this.Logger; tabemailer.HtmlEmailTemplateFilename = Configurator.GetConfig("html_email_template_filename"); tabemailer.TextEmailTemplateFilename = Configurator.GetConfig("text_email_template_filename"); return(tabemailer); }
private void loadSubscriptionsFromRepository() { try { TableauRepository rep = new TableauRepository(Configurator.GetConfig("tableau_server"), Configurator.GetConfig("repository_pw"), "readonly"); rep.logger = this.logger; NpgsqlDataReader dr = rep.query_inactive_subscription_schedules(); Dictionary <string, int> input_box_schedules = new Dictionary <string, int>(); int rowCount = 0; availableSchedulesList.Items.Clear(); if (dr.HasRows == true) { while (dr.Read()) { availableSchedulesList.Items.Add(dr.GetString(1)); input_box_schedules[dr.GetString(1)] = rowCount; rowCount++; } } dr.Close(); // Check the selected schedules from the configs StringCollection checked_schedules = Configurator.GetConfigCollection("selected_schedule_names"); if (checked_schedules != null) { foreach (String sched_name in checked_schedules) { availableSchedulesList.SetItemChecked(input_box_schedules[sched_name], true); } } } catch (NpgsqlException ne) { this.logger.Log("Error with repository while loading the available schedules. Press reload button to try again. Going with existing checked schedules for now"); this.logger.Log(ne.Message); // Fill in the checkbox list based on the existing selected schedules StringCollection checked_schedules = Configurator.GetConfigCollection("selected_schedule_names"); if (checked_schedules != null) { var i = 0; Dictionary <string, int> input_box_schedules = new Dictionary <string, int>(); availableSchedulesList.Items.Clear(); foreach (String sched_name in checked_schedules) { availableSchedulesList.Items.Add(sched_name); input_box_schedules[sched_name] = i; availableSchedulesList.SetItemChecked(input_box_schedules[sched_name], true); i++; } } } catch (ConfigurationException ce) { this.logger.Log("Incorrect credentials for repository readonly user. Cannot connect to repository."); MessageBox.Show("Credentials were not correct for the Repository \"readonly\" user. Please fix"); } }
private string GenerateSingleExport(string exportSite, string exportUsername, string exportViewLocation, string exportAttachmentType, string exportFilename, Dictionary <string, string> viewFilterDictionary) { // Generate Single File try { TableauRepository tabrep = new TableauRepository( Configurator.GetConfig("tableau_server"), Configurator.GetConfig("repository_pw"), "readonly" ); tabrep.logger = this.Logger; Tabcmd tabcmd = new Tabcmd( Configurator.GetConfig("tabcmd_program_location"), Configurator.GetConfig("tableau_server"), Configurator.GetConfig("server_admin_username"), Configurator.GetConfig("server_admin_password"), exportSite, Configurator.GetConfig("tabcmd_config_location"), tabrep, this.Logger ); // Emailer here is used because the Watermarking is built in there. Would it make more sense to move it to Tabcmd eventually, or its own class? BeholdEmailer tabemailer = new BeholdEmailer(tabcmd, Configurator.GetConfig("smtp_server")); Watermarker wm = new Watermarker(); string[] pageLocations = { "top_left", "top_center", "top_right", "bottom_left", "bottom_center", "bottom_right" }; foreach (string pageLocation in pageLocations) { string settingsPageLocation = pageLocation.Split('_')[0] + pageLocation.Split('_')[1].First() + pageLocation.Split('_')[1].Substring(1); wm.SetPageLocationWatermarkFromConfig(pageLocation, Configurator.GetConfigSerializableStringDict(settingsPageLocation)); } string filename = tabemailer.GenerateExportAndWatermark(exportUsername, exportViewLocation, exportAttachmentType, viewFilterDictionary, wm); string[] fileEnding = filename.Split('.'); string finalFilename = String.Format("{0}{1}.{2}", Configurator.GetConfig("export_archive_folder"), exportFilename, fileEnding[fileEnding.Length - 1]); this.Logger.Log(String.Format("Finalizing file and putting it here: {0}", finalFilename)); File.Copy(filename, finalFilename, true); this.Logger.Log(String.Format("Removing original file {0}", filename)); File.Delete(filename); return("Finished single export file creation. Saved to: " + finalFilename); } catch (ConfigurationException ce) { //progress.finish_progress_bar(33); // progress.update_status("Export failed for some reason, most likely bad settings.\nCheck logs for more info"); this.Logger.Log(ce.Message); return("Single export failed. Please see logs for more information."); } }
/* * Test Page Methods */ private void create_test_export(object sender, EventArgs e) { // Needs validation here TextBox[] elements_to_validate = { testFileSaveLocation, testFilename, testSite, testUsernameForImpersonation, testViewLocation }; bool validation = this.validate_set_of_elements(elements_to_validate); if (validation == false) { return; } Progress progress = new Progress(0, "Creating test file"); progress.Show(this); progress.Update(); try { TableauRepository tabrep = new TableauRepository(tableau_server_url.Text, repositoryPW.Text, "readonly"); tabrep.logger = this.logger; Tabcmd tabcmd = new Tabcmd(tabcmdProgramLocation.Text, tableau_server_url.Text, server_admin_username.Text, server_password.Text, testSite.Text, tabcmdConfigLocation.Text, tabrep, this.logger); // Emailer here is used because the Watermarking is built in there. Would it make more sense to move it to Tabcmd eventually, or its own class? BeholdEmailer tabemailer = new BeholdEmailer(tabcmd, emailServer.Text); Watermarker wm = new Watermarker(); string[] page_locations = { "top_left", "top_center", "top_right", "bottom_left", "bottom_center", "bottom_right" }; foreach (string page_location in page_locations) { string settingsPageLocation = page_location.Split('_')[0] + page_location.Split('_')[1].First() + page_location.Split('_')[1].Substring(1); wm.setPageLocationWatermarkFromConfig(page_location, Configurator.GetConfigSerializableStringDict(settingsPageLocation)); } string filename = tabemailer.generate_export_and_watermark(testUsernameForImpersonation.Text, testViewLocation.Text, "fullpdf", new Dictionary <string, string>(), wm); string[] file_ending = filename.Split('.'); string final_filename = String.Format("{0}{1}.{2}", testFileSaveLocation.Text, testFilename.Text, file_ending[file_ending.Length - 1]); this.logger.Log(String.Format("Finalizing file and putting it here: {0}", final_filename)); File.Copy(filename, final_filename, true); this.logger.Log(String.Format("Removing original file {0}", filename)); File.Delete(filename); progress.finish_progress_bar(100); progress.update_status("Export created successfully!"); } catch (ConfigurationException ce) { progress.finish_progress_bar(33); progress.update_status("Export failed for some reason, most likely bad settings.\nCheck logs for more info"); this.logger.Log(ce.Message); } }
private BeholdEmailer create_behold_emailer_from_config(string site) { TableauRepository tabrep = new TableauRepository(tableau_server_url.Text, repositoryPW.Text, "readonly"); tabrep.logger = this.logger; Tabcmd tabcmd = new Tabcmd(tabcmdProgramLocation.Text, tableau_server_url.Text, server_admin_username.Text, server_password.Text, site, tabcmdConfigLocation.Text, tabrep, this.logger); BeholdEmailer tabemailer = new BeholdEmailer(tabcmd, this.create_smtp_client_from_config()); tabemailer.logger = this.logger; tabemailer.html_email_template_filename = htmlEmailFilename.Text; tabemailer.text_email_template_filename = textEmailFilename.Text; return(tabemailer); }
public Tabcmd(string tabcmd_folder, string tableau_server_url, string username, string password, string site, string tabcmd_config_location, TableauRepository TableauRepository) { this.tabcmd_folder = tabcmd_folder; this.username = username; this.password = password; this.site = site; this.tableau_server_url = tableau_server_url; this.tabcmd_config_filename = "tabcmd-session.xml"; this.tabcmd_config_location = tabcmd_config_location; this.repository = TableauRepository; // This preps tabcmd for subsequent calls this.log("Preping the tabcmd admin session"); this.create_tabcmd_admin_session(); this.logger = null; }
public Tabcmd(string tabcmd_folder, string tableau_server_url, string username, string password, string site, string tabcmd_config_location, TableauRepository TableauRepository) { this.tabcmdFolderLocation = tabcmd_folder; this.username = username; this.password = password; this.Site = site; this.TableauServerUrl = tableau_server_url; this.tabcmdConfigFilename = "tabcmd-session.xml"; this.tabcmdConfigLocation = tabcmd_config_location; this.Repository = TableauRepository; // This preps tabcmd for subsequent calls this.Log("Preping the tabcmd admin session"); this.CreateTabcmdAdminSession(); this.Logger = null; }
public Tabcmd(string tabcmdFolderLocation, string tableauServerUrl, string username, string password, string site, string repositoryPassword, string tabcmdConfigurationFileLocation) { // tabcmd program configurations are stored within an XML file this.tabcmdFolderLocation = tabcmdFolderLocation; this.tabcmdConfigFilename = "tabcmd-session.xml"; this.tabcmdConfigLocation = tabcmdConfigurationFileLocation; // Open the configuration file and test whether it resembles the real file. // Should really replace with XML reader to make this better, but in the end this part needs to be deprecated for the APIs try { StreamReader tabcmdConfigurationFile = new StreamReader(tabcmdConfigurationFileLocation + tabcmdConfigFilename); // Read first line tabcmdConfigurationFile.ReadLine(); // Read second line, should be <session>. May come up with better test string second_line = tabcmdConfigurationFile.ReadLine(); if (second_line.Contains("<session>") == false) { throw new ConfigurationException("tabcmd-session.xml file information is incorrect. File is not tabcmd-session.xml"); } tabcmdConfigurationFile.Close(); } catch (IOException) { throw new ConfigurationException("tabcmd-config file information is incorrect. Config file could not be opened"); } this.username = username; this.password = password; this.Site = site; this.TableauServerUrl = tableauServerUrl; this.repositoryPassword = repositoryPassword; this.Repository = new TableauRepository(this.TableauServerUrl, this.repositoryPassword, "readonly"); // This preps tabcmd for subsequent calls this.Log("Preping the tabcmd admin session"); this.CreateTabcmdAdminSession(); this.Logger = null; }
public Tabcmd(string tabcmd_folder, string tableau_server_url, string username, string password, string site, string repository_password, string tabcmd_config_location) { // Tabcmd program configurations this.tabcmd_folder = tabcmd_folder; this.tabcmd_config_filename = "tabcmd-session.xml"; this.tabcmd_config_location = tabcmd_config_location; // Open the configuration file and test whether it resembles the real file try { StreamReader tabcmd_config = new StreamReader(tabcmd_config_location + tabcmd_config_filename); // Read first line tabcmd_config.ReadLine(); // Read second line, should be <session>. May come up with better test string second_line = tabcmd_config.ReadLine(); if (second_line.Contains("<session>") == false) { throw new ConfigurationException("tabcmd-session.xml file information is incorrect. File is not tabcmd-session.xml"); } tabcmd_config.Close(); } catch (IOException) { throw new ConfigurationException("tabcmd-config file information is incorrect. Config file could not be opened"); } this.username = username; this.password = password; this.site = site; this.tableau_server_url = tableau_server_url; this.repository_pw = repository_password; this.repository = new TableauRepository(this.tableau_server_url, this.repository_pw, "readonly"); // This preps tabcmd for subsequent calls this.log("Preping the tabcmd admin session"); this.create_tabcmd_admin_session(); this.logger = null; }
/* * Schedules Tab * */ private void runSchedules_TimedEvent(Object source, EventArgs e) { // Only run on one minute after every 15 if (DateTime.Now.Minute == 1 || DateTime.Now.Minute == 16 || DateTime.Now.Minute == 31 || DateTime.Now.Minute == 46) { this.logger.Log("Schedule checks begin"); this.scheduledEmailsStatus.Text = "Scheduled Emails are running"; try { // Read the schedules that are currently in the repository, to update the active schedule queue TableauRepository rep = new TableauRepository(Configurator.GetConfig("tableau_server"), Configurator.GetConfig("repository_pw"), "readonly"); rep.logger = this.logger; NpgsqlDataReader dr = rep.query_inactive_subscription_schedules_for_next_run_time(); if (dr.HasRows == true) { using (StreamWriter active_schedules_file = new StreamWriter(this.active_schedules_queue_filename, false, new UTF8Encoding())) { while (dr.Read()) { string sched_name = dr.GetString(0); string sched_next_run_time; //Although server time is usually UTC, the time is later compared with current time converted to UTC too. DateTime serverTime = dr.GetDateTime(1); sched_next_run_time = serverTime.ToString(); this.logger.Log(String.Format("Next scheduled run time (UTC) is {0}", sched_next_run_time)); // Only add if the sched_name is in the checked schedules int num_checked_items = availableSchedulesList.CheckedItems.Count; string[] checked_schedule_names = new string[num_checked_items]; var k = 0; foreach (object itemChecked in availableSchedulesList.CheckedItems) { checked_schedule_names[k] = itemChecked.ToString(); k++; } string[] sched = new string[2] { sched_name, sched_next_run_time }; bool schedule_exists_in_queue = false; foreach (string[] queued_sched in this.active_schedules) { if (queued_sched[0] == sched_name && queued_sched[1] == sched_next_run_time) { schedule_exists_in_queue = true; this.logger.Log(String.Format("Schedule {0} at {1} already exists in queue", sched_name, sched_next_run_time)); } } if (schedule_exists_in_queue == false) { // Only add checked schedule names if (checked_schedule_names.Any(sched.Contains) == true) { this.active_schedules.Add(sched); this.logger.Log(String.Format("Schedule {0} at {1} added to the queue", sched_name, sched_next_run_time)); active_schedules_file.WriteLine(String.Format("{0}|{1}", sched_name, sched_next_run_time)); } } } } } dr.Close(); } catch (NpgsqlException ne) { this.logger.Log("Connecting to repository to update the active queue failed. Ignoring for now, will update at next interval"); this.logger.Log(ne.Message); } // Look at the Active Queue and determine if anything is past it's due date foreach (string[] queued_sched in this.active_schedules.Reverse <string[]>()) { if (DateTime.Now.ToUniversalTime() > DateTime.Parse(queued_sched[1])) { this.logger.Log(String.Format("Schedule {0} at {1} is now eligible to be run.", queued_sched[0], queued_sched[1])); bool result = send_email(queued_sched[0]); if (result == true) { this.logger.Log(String.Format("Schedule {0} at {1} has run successfully. Removing from queue", queued_sched[0], queued_sched[1])); } else { //Suppose a schedule contains multiple subscriptions and one of them fails, the original app will send pdf to everyone else every 15 minutes. //This prevents it by removing unsuccessful sessions. this.logger.Log(String.Format("Schedule {0} at {1} failed (maybe partially). Removing from queue", queued_sched[0], queued_sched[1])); } // Write completed schedules into the schedule_run log this.completed_schedules_file.WriteLine(String.Format("{0}|{1}", queued_sched[0], queued_sched[1])); this.active_schedules.Remove(queued_sched); } } // Write the queues to the active_schedules files using (StreamWriter active_schedules_file = new StreamWriter(this.active_schedules_queue_filename, false, new UTF8Encoding())) { foreach (string[] queued_sched in this.active_schedules) { active_schedules_file.WriteLine(String.Format("{0}|{1}", queued_sched[0], queued_sched[1])); } } this.logger.Log("Schedule check completed successfully"); this.scheduledEmailsStatus.Text = "Waiting to Run Next Scheduled Emails"; } }
private void updateSchedulesQueue() { var activityId = this.nextActivityId; this.nextActivityId++; WriteToActivityGrid("Checking for schedules to run in the repository", activityId); this.Logger.Log("Schedule checks begin"); try { // Read the schedules that are currently in the repository, to update the active schedule queue TableauRepository rep = new TableauRepository(Configurator.GetConfig("tableau_server"), Configurator.GetConfig("repository_pw"), "readonly"); rep.logger = this.Logger; //this.Logger.Log("Starting to read from the repository"); NpgsqlDataReader dr = rep.QueryInactiveSubscriptionSchedulesForNextRunTime(); if (dr.HasRows == true) { //this.Logger.Log("Opening the active schedules queue file"); using (StreamWriter activeSchedulesQueueFileWriter = new StreamWriter(this.ActiveSchedulesQueueFilename, false, new UTF8Encoding())) { //this.Logger.Log("Reading from the result set "); while (dr.Read()) { // this.Logger.Log("Working inside the result set "); string scheduleName = dr.GetString(0); string scheduleNextRunTime = dr.GetDateTime(1).ToString(); //this.Logger.Log(String.Format("Schedule here {0} {1}", scheduleName, scheduleNextRunTime)); // Because the selections are stored instantly, load from the saved collectionr rather than the control // It is possible the control has not been redrawn at the time List <string> selectedScheduleNames = new List <string>() { }; StringCollection savedSchedules = Configurator.GetConfigCollection("selected_schedule_names"); if (savedSchedules != null) { foreach (String savedScheduleName in savedSchedules) { selectedScheduleNames.Add(savedScheduleName); } } string[] scheduleInfo = new string[2] { scheduleName, scheduleNextRunTime }; bool doesScheduleExistInQueue = false; // See if what is in the activeSchedulesQueue file is a checked schedule still foreach (string[] activeSchedule in this.ActiveSchedules) { if (activeSchedule[0] == scheduleName && activeSchedule[1] == scheduleNextRunTime) { this.Logger.Log(String.Format("Schedule {0} at {1} already in the schedules queue", scheduleName, scheduleNextRunTime)); doesScheduleExistInQueue = true; } } if (doesScheduleExistInQueue == false) { // Only add checked schedule names if (selectedScheduleNames.Any(scheduleInfo.Contains) == true) { this.ActiveSchedules.Add(scheduleInfo); WriteToActivityGrid(String.Format("Schedule {0} at {1} added to the schedules queue", scheduleName, scheduleNextRunTime), activityId); this.Logger.Log(String.Format("Schedule {0} at {1} added to the schedules queue", scheduleName, scheduleNextRunTime)); activeSchedulesQueueFileWriter.WriteLine(String.Format("{0}|{1}", scheduleName, scheduleNextRunTime)); } else { this.Logger.Log(String.Format("Schedule {0} at {1} not added to schedules queue because it is not selected", scheduleName, scheduleNextRunTime)); } } } } } else { this.Logger.Log("No rows found in the query for new schedules"); } dr.Close(); } catch (NpgsqlException ne) { this.Logger.Log("Connecting to repository to update the active queue failed. Ignoring for now, will update at next interval"); this.Logger.Log(ne.Message); } WriteToActivityGrid("Completed checking for new schedules", activityId); // Look at the Active Queue and determine if anything is past it's due date foreach (string[] queuedSchedule in this.ActiveSchedules.Reverse <string[]>()) { if (DateTime.Now.ToUniversalTime() > DateTime.Parse(queuedSchedule[1])) { activityId = this.nextActivityId; this.nextActivityId++; this.Logger.Log(String.Format("Schedule {0} at {1} is now eligible to be run.", queuedSchedule[0], queuedSchedule[1])); WriteToActivityGrid(String.Format("Schedule {0} at {1} is now eligible to be run. Queuing to run.", queuedSchedule[0], queuedSchedule[1]), activityId); // Add to the actionQueue at the top asyncActionQueue.Insert(0, () => { var queuedScheduleName = queuedSchedule[0]; var queuedScheduleRunTime = queuedSchedule[1]; WriteToActivityGrid(String.Format("Running Schedule {0} at {1}.", queuedSchedule[0], queuedSchedule[1]), activityId); bool result = SendEmail(queuedScheduleName); // Even if failure, remove from active schedules queue this.Logger.Log(String.Format("Removing {0} at {1} from active schedules queue", queuedSchedule[0], queuedSchedule[1])); this.ActiveSchedules.Remove(queuedSchedule); // Write the remaining queues. using (StreamWriter activeSchedulesQueueFileWriter = new StreamWriter(this.ActiveSchedulesQueueFilename, false, new UTF8Encoding())) { foreach (string[] currentlyQueuedSchedules in this.ActiveSchedules) { activeSchedulesQueueFileWriter.WriteLine(String.Format("{0}|{1}", currentlyQueuedSchedules[0], currentlyQueuedSchedules[1])); } } if (result) { WriteToActivityGrid(String.Format("Completed Schedule {0} at {1}.", queuedScheduleName, queuedScheduleRunTime), activityId); return(String.Format("Completed Schedule {0} at {1}.", queuedScheduleName, queuedScheduleRunTime)); } else { this.ActiveSchedules.Remove(queuedSchedule); WriteToActivityGrid(String.Format("Schedule {0} at {1} failed, see log.", queuedScheduleName, queuedScheduleRunTime), activityId); return(String.Format("Schedule {0} at {1} failed, see log.", queuedScheduleName, queuedScheduleRunTime)); } } ); // Launch the next action in the queue, if possible try { actionQueueBackgroundWorker.RunWorkerAsync(asyncActionQueue[0]); } // The queue response will launch the next action once it is finished catch (InvalidOperationException) { this.Logger.Log("Action queued but other action currently running"); } } } }