protected void Button1_Click(object sender, EventArgs e) {
            object tokenObject = this.ViewState["token"];
            if(tokenObject == null) {
                passwordUpdate.Visible = false;
                invalidToken.Visible = true;
                return;
            }

            var user = SRPUser.UpdatePasswordByToken(tokenObject.ToString(),
                                                     Password.Text);

            if(user == null) {
                passwordUpdate.Visible = false;
                invalidToken.Visible = true;
                return;
            }

            // user requested a password for an email address that is not in the database
            // if account doesn't exist, send an email saying so
            var values = new {
                SystemName = SRPSettings.GetSettingValue("SysName", user.TenID),
                ContactName = SRPSettings.GetSettingValue("ContactName", user.TenID),
                ContactEmail = SRPSettings.GetSettingValue("ContactEmail", user.TenID),
                RemoteAddress = new Tools.WebTools().RemoteUserAddress(Request),
                UserEmail = user.EmailAddress,
                ControlRoomLink = string.Format("{0}{1}",
                                                BaseUrl,
                                                "/ControlRoom/"),
                PasswordResetSuccessSubject = SRPResources.PasswordEmailSuccessSubject
            };

            this.Log().Info("Password reset process for {0} complete from {1}",
                            values.UserEmail,
                            values.RemoteAddress);

            // TODO email - move this template out to the database
            StringBuilder body = new StringBuilder();
            body.Append("<p>The password reset for your {SystemName} account is now complete.</p>");
            body.Append("<p>You may now <a href=\"{ControlRoomLink}\">log in</a> using your new ");
            body.Append("password.</p>");
            body.Append("<p>If you have any comments or questions, please contact ");
            body.Append("{ContactName} at <a href=\"mailto:{ContactEmail}\">{ContactEmail}");
            body.Append("</a>.</p>");
            body.Append("<p style=\"font-size: smaller;\"><em>This password request was ");
            body.Append("completed from: {RemoteAddress}.</em></p>");

            new EmailService().SendEmail(user.EmailAddress,
                                         "{SystemName} - {PasswordResetSuccessSubject}".FormatWith(values),
                                         body.ToString().FormatWith(values));
        
            Response.Redirect("Login.aspx");
        }
        protected void btnLogin_Click(object sender, EventArgs e) {
            if(Page.IsValid) {
                object tokenObject = this.ViewState["token"];
                if(tokenObject == null) {
                    new SessionTools(Session).AlertPatron(GetResourceString("password-recovery-expired"),
                                                          PatronMessageLevels.Warning,
                                                          "exclamation-sign");
                    Response.Redirect("~/Recover.aspx");
                    return;
                }

                var user = Patron.UpdatePasswordByToken(tokenObject.ToString(),
                                                        NPassword.Text);

                if(user == null) {
                    new SessionTools(Session).AlertPatron(GetResourceString("password-recovery-expired"),
                                                          PatronMessageLevels.Warning,
                                                          "exclamation-sign");
                    Response.Redirect("~/Recovery.aspx");
                    return;
                }

                var values = new {
                    SystemName = SRPSettings.GetSettingValue("SysName", user.TenID),
                    ContactName = SRPSettings.GetSettingValue("ContactName", user.TenID),
                    ContactEmail = SRPSettings.GetSettingValue("ContactEmail", user.TenID),
                    RemoteAddress = Request.UserHostAddress,
                    UserEmail = user.EmailAddress,
                    Username = user.Username,
                    LoginLink = string.Format("{0}{1}",
                                              WebTools.GetBaseUrl(Request),
                                              "/Login.aspx"),
                    PasswordResetSuccessSubject = "Your password has been reset!"
                };

                this.Log().Info("Password reset process for {0} ({1}) complete from {2}",
                                values.Username,
                                values.UserEmail,
                                values.RemoteAddress);

                // TODO email - move this template out to the database
                StringBuilder body = new StringBuilder();
                body.Append("<p>The password change has been successful for the {SystemName} account: {Username}.</p>");
                body.Append("<p>You may now <a href=\"{LoginLink}\">log in</a> using your new password.</p>");
                body.Append("<p>If you have any comments or questions, please contact ");
                body.Append("{ContactName} at <a href=\"mailto:{ContactEmail}\">{ContactEmail}</a>.</p>");
                body.Append("<p style=\"font-size: smaller;\"><em>This password request was ");
                body.Append("completed from: {RemoteAddress}.</em></p>");

                new EmailService().SendEmail(user.EmailAddress,
                                             "{SystemName} - {PasswordResetSuccessSubject}".FormatWith(values),
                                             body.ToString().FormatWith(values));


                var st = new SessionTools(Session);
                st.EstablishPatron(user);
                st.AlertPatron(GetResourceString("Your password has been reset!"),
                                                 glyphicon: "ok");

                TestingBL.CheckPatronNeedsPreTest();
                TestingBL.CheckPatronNeedsPostTest();

                Response.Redirect("~");
            }
        }
        protected List<string> ConfigureTheGRA()
        {
            var issues = new List<string>();
            Configuration webConfig = null;

            try
            {
                webConfig = WebConfigurationManager.OpenWebConfiguration("~");
            }
            catch (Exception ex)
            {
                issues.Add(string.Format("Could not read the Web.config file on the disk (this is probably due to permissions): {0}", ex.Message));
                return issues;
            }
            try
            {
                webConfig.Save(ConfigurationSaveMode.Minimal);
            }
            catch (Exception ex)
            {
                issues.Add(string.Format("Could not write to the Web.config file on the disk (this is probably due to permissions): {0}", ex.Message));
                return issues;
            }

            var ownerBuilder = new SqlConnectionStringBuilder();
            ownerBuilder.DataSource = DatabaseServer.Text;
            ownerBuilder.InitialCatalog = DatabaseCatalog.Text;
            if (!DatabaseServer.Text.Contains("(localdb)"))
            {
                ownerBuilder.UserID = DatabaseOwnerUser.Text;
                ownerBuilder.Password = ViewState[DbOwnerKey].ToString();
            }

            using (var sqlConnection = new SqlConnection(ownerBuilder.ConnectionString))
            {
                // do database script run
                var path = CreateSchemaPath;
                this.Log().Info("Creating database schema");
                var schemaIssues = ExecuteSqlFile(path, sqlConnection);

                if (schemaIssues.Count > 0)
                {
                    return schemaIssues;
                }

                if (ReadingProgram.SelectedIndex == 0)
                {
                    // single program
                    path = Insert1ProgramPath;
                }
                else
                {
                    // multiple programs
                    path = Insert4ProgramsPath;
                }
                var insertIssues = ExecuteSqlFile(path, sqlConnection);

                if (insertIssues.Count > 0)
                {
                    return insertIssues;
                }

                // update email address
                sqlConnection.Open();
                try
                {
                    // update the sysadmin user's email
                    SqlCommand updateEmail = new SqlCommand("UPDATE [SRPUser] SET [EmailAddress] = @emailAddress WHERE [Username] = 'sysadmin';",
                                                            sqlConnection);
                    updateEmail.Parameters.AddWithValue("@emailAddress", MailAddress.Text);
                    updateEmail.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    string error = string.Format("Unable to update administrative email address: {0}",
                                                 ex);
                    this.Log().Error(error);
                }
                try
                {
                    // update the sysadmin contact email and mail from address
                    // TODO email - provide better setup for email
                    SqlCommand updateEmail = new SqlCommand("UPDATE [SRPSettings] SET [Value] = @emailAddress WHERE [Name] IN ('ContactEmail', 'FromEmailAddress');",
                                                            sqlConnection);
                    updateEmail.Parameters.AddWithValue("@emailAddress", MailAddress.Text);
                    updateEmail.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    string error = string.Format("Unable to update administrative email address: {0}",
                                                 ex);
                    this.Log().Error(error);
                }
                sqlConnection.Close();
            }

            // data inserted, update Web.config
            try
            {
                var userBuilder = new SqlConnectionStringBuilder();
                userBuilder.DataSource = DatabaseServer.Text;
                userBuilder.InitialCatalog = DatabaseCatalog.Text;
                if (!DatabaseServer.Text.Contains("(localdb)"))
                {
                    userBuilder.UserID = DatabaseUserUser.Text;
                    userBuilder.Password = ViewState[DbUserKey].ToString();
                }

                var csSection = (ConnectionStringsSection)webConfig.GetSection("connectionStrings");
                csSection.ConnectionStrings[GlobalUtilities.SRPDBConnectionStringName].ConnectionString = userBuilder.ConnectionString;

                var appSection = (AppSettingsSection)webConfig.GetSection("appSettings");
                if (appSection.Settings[AppSettingKeys.GraConfigured.ToString()] == null)
                {
                    appSection.Settings.Add(AppSettingKeys.GraConfigured.ToString(), "1");
                }
                else
                {
                    appSection.Settings[AppSettingKeys.GraConfigured.ToString()].Value = "1";
                }

                webConfig.Save(ConfigurationSaveMode.Minimal);

                var mailSection = (MailSettingsSectionGroup)webConfig.GetSectionGroup("system.net/mailSettings");
                var network = mailSection.Smtp.Network;

                if (!string.IsNullOrEmpty(MailServer.Text))
                {
                    network.Host = MailServer.Text;
                    mailSection.Smtp.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
                }

                mailSection.Smtp.From = null;


                if (!string.IsNullOrEmpty(MailPort.Text))
                {
                    int port = 0;
                    if (int.TryParse(MailPort.Text, out port))
                    {
                        network.Port = port;
                    }
                }

                if (!string.IsNullOrEmpty(MailLogin.Text))
                {
                    network.UserName = MailLogin.Text;
                }

                if (ViewState[MailPwKey] != null && !string.IsNullOrEmpty(ViewState[MailPwKey].ToString()))
                {
                    network.Password = ViewState[MailPwKey].ToString();
                }

                webConfig.Save(ConfigurationSaveMode.Minimal);
            }
            catch (Exception ex)
            {
                string error = string.Format("Couldn't update Web.config with new connection string: {0}", ex.Message);
                this.Log().Error(error);
                issues.Add(error);
            }



            if (issues.Count == 0)
            {
                this.Log().Info(() => "Great Reading Adventure setup complete!");
                try
                {
                    // TODO email - move this template out to the database
                    var values = new
                    {
                        SystemName = "The Great Reading Adventure",
                        ControlRoomLink = string.Format("{0}{1}",
                                                        WebTools.GetBaseUrl(Request),
                                                        "/ControlRoom/"),
                    };

                    StringBuilder body = new StringBuilder();
                    body.Append("<p>Congratulations! You have successfully configured ");
                    body.Append("{SystemName}!</p><p>You may now ");
                    body.Append("<a href=\"{ControlRoomLink}\">log in</a> using the default ");
                    body.Append("system administrator credentials.</p><p>For more information on ");
                    body.Append("setting up and using the {SystemName} software, feel free to ");
                    body.Append("visit the <a href=\"http://manual.greatreadingadventure.com/\">manual</a> ");
                    body.Append("and <a href=\"http://forum.greatreadingadventure.com/\">forum</a>.");
                    body.Append("</p>");

                    new EmailService().SendEmail(MailAddress.Text,
                                                 "{SystemName} - Setup complete!"
                                                 .FormatWith(values),
                                                 body.ToString().FormatWith(values));
                    this.Log().Info(() => "Welcome email sent.");
                }
                catch (Exception ex)
                {
                    this.Log().Error(() => "Welcome email sending failure: {Message}"
                                           .FormatWith(ex));
                }

                return null;
            }
            else
            {
                return issues;
            }
        }