private MailMessage GenerateReminderForPerson(Person person, List <Project> projects) { var projectListAsHtmlStrings = GenerateProjectListAsHtmlStrings( projects); var projectsRequiringAnUpdateUrl = SitkaRoute <ProjectUpdateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.MyProjectsRequiringAnUpdate()); var emailContent = GetEmailContentWithGeneratedSignature(projectsRequiringAnUpdateUrl, person.FullNameFirstLast, String.Join("<br/>", projectListAsHtmlStrings)); var htmlView = AlternateView.CreateAlternateViewFromString(emailContent, null, "text/html"); htmlView.LinkedResources.Add( new LinkedResource(new MemoryStream(ToolLogo.FileResourceData), "img/jpeg") { ContentId = "tool-logo" }); var mailMessage = new MailMessage { Subject = ReminderEmailSubject, IsBodyHtml = true }; mailMessage.AlternateViews.Add(htmlView); return(mailMessage); }
public static void SendApprovalMessage(List <Person> peopleToCc, ProjectUpdateBatch projectUpdateBatch) { Check.Require(projectUpdateBatch.ProjectUpdateState == ProjectUpdateState.Approved, "Need to be in Approved state to send the Approved email!"); var latestProjectUpdateHistorySubmitted = projectUpdateBatch.LatestProjectUpdateHistorySubmitted; var submitterPerson = latestProjectUpdateHistorySubmitted.UpdatePerson; var emailsToSendTo = new List <string> { submitterPerson.Email }; var personNames = submitterPerson.FullNameFirstLast; var primaryContactPerson = projectUpdateBatch.Project.GetPrimaryContact(); if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { if (string.IsNullOrEmpty(primaryContactPerson.Email)) { Logger.Warn($"Primary Contact is missing email address and will not get an Approval Message. Primary Contact ID:{primaryContactPerson.PersonID} Primary Contact Name:{primaryContactPerson.FullNameFirstLast} Project Update Batch ID:{projectUpdateBatch.ProjectUpdateBatchID} "); } else { emailsToSendTo.Add(primaryContactPerson.Email); personNames += $" and {primaryContactPerson.FullNameFirstLast}"; } } var approverPerson = projectUpdateBatch.LastUpdatePerson; var detailUrl = SitkaRoute <ProjectController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Detail(projectUpdateBatch.Project)); var message = $@" Dear {personNames}, <p> The update submitted for {FieldDefinition.Project.GetFieldDefinitionLabel()} {projectUpdateBatch.Project.DisplayName} on { latestProjectUpdateHistorySubmitted.TransitionDate.ToStringDate() } was approved by {approverPerson.FullNameFirstLastAndOrg}. </p> <p> There is no action for you to take - this is simply a notification email. The updates for this {FieldDefinition.Project.GetFieldDefinitionLabel()} are now visible to the general public on this {FieldDefinition.Project.GetFieldDefinitionLabel()}'s detail page: </p> <p> <a href=""{detailUrl}"">View this {FieldDefinition.Project.GetFieldDefinitionLabel()}</a> </p> Thank you for keeping your {FieldDefinition.Project.GetFieldDefinitionLabel()} information and accomplishments up to date!<br /> {$"- {MultiTenantHelpers.GetToolDisplayName()} team"} "; var subject = $"The update for {FieldDefinition.Project.GetFieldDefinitionLabel()} {projectUpdateBatch.Project.DisplayName} was approved"; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; SendMessageAndLogNotificationForProjectUpdateTransition(projectUpdateBatch, mailMessage, emailsToSendTo, new List <string> { approverPerson.Email }, peopleToCc.Select(x => x.Email).ToList(), NotificationType.ProjectUpdateApproved); }
public WebServiceProjectKeyPhoto(Project project) { ProjectID = project.ProjectID; ProjectName = project.ProjectName; KeyPhotoUrl = project.KeyPhoto != null ? SitkaRoute <FileResourceController> .BuildAbsoluteUrlHttpsFromExpression(x => x.DisplayResource(project.KeyPhoto.FileResource.FileResourceGUIDAsString)) : ViewUtilities.NoneString; }
public static void SendReturnedMessage(Project project) { var submitterPerson = project.ProposingPerson; var fieldDefinitionLabelProject = FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel(); var subject = $@"Your {fieldDefinitionLabelProject} ""{project.GetDisplayName().ToEllipsifiedString(80)}"" was not approved"; var basicsUrl = SitkaRoute <ProjectCreateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.EditBasics(project.ProjectID)); var message = $@" <p>Dear {submitterPerson.GetFullNameFirstLast()},</p> <p>The {MultiTenantHelpers.GetToolDisplayName()} {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} submitted on {project.SubmissionDate.ToStringDate()} has been returned for further review.</p> <p>The {fieldDefinitionLabelProject} was returned by {project.ReviewedByPerson.GetFullNameFirstLastAndOrg()}. Please review this {fieldDefinitionLabelProject} and address the comments that {project.ReviewedByPerson.FirstName} left for you. If you have questions please email: {project.ReviewedByPerson.Email}.</p> <a href=""{basicsUrl}"">View this {fieldDefinitionLabelProject}</a></p> <p>Thank you for using the {MultiTenantHelpers.GetToolDisplayName()}</p> <p>{$"- {MultiTenantHelpers.GetToolDisplayName()} team"}<br/><br/><img src=""cid:tool-logo"" width=""160"" /></p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var tenantAttribute = MultiTenantHelpers.GetTenantAttributeFromCache(); var toolLogo = tenantAttribute.TenantSquareLogoFileResourceInfo ?? tenantAttribute.TenantBannerLogoFileResourceInfo; var htmlView = AlternateView.CreateAlternateViewFromString(message, null, "text/html"); htmlView.LinkedResources.Add( new LinkedResource(new MemoryStream(toolLogo.FileResourceData.Data), "img/jpeg") { ContentId = "tool-logo" }); mailMessage.AlternateViews.Add(htmlView); var emailsToSendTo = new List <string> { submitterPerson.Email }; var primaryContactPerson = project.PrimaryContactPerson; if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { emailsToSendTo.Add(primaryContactPerson.Email); } var contactsWhoCanManageProject = project.GetContactsWhoCanManageProject(); foreach (var contact in contactsWhoCanManageProject) { if (!string.Equals(contact.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase) && (primaryContactPerson == null || !string.Equals(contact.Email, primaryContactPerson.Email, StringComparison.InvariantCultureIgnoreCase))) { emailsToSendTo.Add(contact.Email); } } var emailsToReplyTo = new List <string> { project.ReviewedByPerson.Email }; var emailsToCc = project.GetProjectStewardPeople().Select(x => x.Email).ToList(); SendMessageAndLogNotification(project, mailMessage, emailsToSendTo, emailsToReplyTo, emailsToCc, NotificationType.ProjectReturned); }
public static void SendSubmittedMessage(List <Person> peopleToNotify, ProjectUpdateBatch projectUpdateBatch) { Check.Require(projectUpdateBatch.ProjectUpdateState == ProjectUpdateState.Submitted, "Need to be in Submitted state to send the Submitted email!"); var latestProjectUpdateHistorySubmitted = projectUpdateBatch.GetLatestProjectUpdateHistorySubmitted(); var submitterPerson = latestProjectUpdateHistorySubmitted.UpdatePerson; var submitterEmails = new List <string> { submitterPerson.Email }; var primaryContactPerson = projectUpdateBatch.Project.GetPrimaryContact(); if (primaryContactPerson != null && !string.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { submitterEmails.Add(primaryContactPerson.Email); } var contactsWhoCanManageProject = projectUpdateBatch.Project.GetContactsWhoCanManageProject(); foreach (var contact in contactsWhoCanManageProject) { if (!string.Equals(contact.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase) && (primaryContactPerson == null || !string.Equals(contact.Email, primaryContactPerson.Email, StringComparison.InvariantCultureIgnoreCase))) { submitterEmails.Add(contact.Email); } } var emailsToSendTo = peopleToNotify.Select(x => x.Email).ToList(); var subject = $"The update for {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} {projectUpdateBatch.Project.GetDisplayName()} was submitted"; var instructionsUrl = SitkaRoute <ProjectUpdateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Instructions(projectUpdateBatch.Project)); var message = $@" <p>The update for {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} {projectUpdateBatch.Project.GetDisplayName()} on { latestProjectUpdateHistorySubmitted.TransitionDate.ToStringDate() } was just submitted by {submitterPerson.GetFullNameFirstLastAndOrg()}.</p> <p>Please review and Approve or Return it at your earliest convenience.<br /> <a href=""{instructionsUrl}"">View this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} update</a></p> {$"- {MultiTenantHelpers.GetToolDisplayName()} team"}<br/><br/><img src=""cid:tool-logo"" width=""160"" /> <p>You received this email because you are assigned to receive support notifications within the ProjectFirma tool.</p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var tenantAttribute = MultiTenantHelpers.GetTenantAttributeFromCache(); var toolLogo = tenantAttribute.TenantSquareLogoFileResourceInfo ?? tenantAttribute.TenantBannerLogoFileResourceInfo; var htmlView = AlternateView.CreateAlternateViewFromString(message, null, "text/html"); htmlView.LinkedResources.Add( new LinkedResource(new MemoryStream(toolLogo.FileResourceData.Data), "img/jpeg") { ContentId = "tool-logo" }); mailMessage.AlternateViews.Add(htmlView); SendMessageAndLogNotificationForProjectUpdateTransition(projectUpdateBatch, mailMessage, emailsToSendTo, submitterEmails, new List <string>(), NotificationType.ProjectUpdateSubmitted); }
public static void SendSubmittedMessage(Project project) { var submitterPerson = project.ProposingPerson; var subject = $"A {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} was submitted by {submitterPerson.GetFullNameFirstLastAndOrg()}"; var basicsUrl = SitkaRoute <ProjectCreateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.EditBasics(project.ProjectID)); var message = $@" <p>A new {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}, “{project.GetDisplayName()}”, was submitted.</p> <p>The {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} was submitted on {project.ProposingDate.ToStringDate()} by { submitterPerson.GetFullNameFirstLastAndOrg() }.<br /> <p>Please review and Approve or Return it at your earliest convenience.</p> <a href=""{basicsUrl}"">View this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}</a></p> {$"- {MultiTenantHelpers.GetToolDisplayName()} team"}<br/><br/><img src=""cid:tool-logo"" width=""160"" /> <p>You received this email because you are assigned to receive support notifications within the ProjectFirma tool.</p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var tenantAttribute = MultiTenantHelpers.GetTenantAttributeFromCache(); var toolLogo = tenantAttribute.TenantSquareLogoFileResourceInfo ?? tenantAttribute.TenantBannerLogoFileResourceInfo; var htmlView = AlternateView.CreateAlternateViewFromString(message, null, "text/html"); htmlView.LinkedResources.Add( new LinkedResource(new MemoryStream(toolLogo.FileResourceData.Data), "img/jpeg") { ContentId = "tool-logo" }); mailMessage.AlternateViews.Add(htmlView); var emailsToSendTo = project.GetProjectStewardPeople().Select(x => x.Email).Distinct().ToList(); var emailsToReplyTo = new List <string> { submitterPerson.Email }; var primaryContactPerson = project.PrimaryContactPerson; if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { emailsToReplyTo.Add(primaryContactPerson.Email); } var contactsWhoCanManageProject = project.GetContactsWhoCanManageProject(); foreach (var contact in contactsWhoCanManageProject) { if (!string.Equals(contact.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase) && (primaryContactPerson == null || !string.Equals(contact.Email, primaryContactPerson.Email, StringComparison.InvariantCultureIgnoreCase))) { emailsToReplyTo.Add(contact.Email); } } var emailsToCc = new List <string>(); SendMessageAndLogNotification(project, mailMessage, emailsToSendTo, emailsToReplyTo, emailsToCc, NotificationType.ProjectSubmitted); }
public ProjectMapViewData(Person currentPerson, Models.FirmaPage firmaPage, ProjectLocationsMapInitJson projectLocationsMapInitJson, ProjectLocationsMapViewData projectLocationsMapViewData, Dictionary <ProjectLocationFilterTypeSimple, IEnumerable <SelectListItem> > projectLocationFilterTypesAndValues, string projectLocationsUrl, string filteredProjectsWithLocationAreasUrl, List <ProjectMapLocationJson> projectMapLocationJsons) : base(currentPerson, firmaPage) { PageTitle = $"{Models.FieldDefinition.Project.GetFieldDefinitionLabel()} Map"; ProjectLocationsMapInitJson = projectLocationsMapInitJson; ProjectLocationFilterTypesAndValues = projectLocationFilterTypesAndValues; ProjectLocationsMapViewData = projectLocationsMapViewData; ProjectLocationsUrl = projectLocationsUrl; FilteredProjectsWithLocationAreasUrl = filteredProjectsWithLocationAreasUrl; ProjectMapViewDataForAngular = new ProjectMapViewDataForAngular(projectLocationsMapInitJson, projectLocationsMapInitJson.ProjectLocationsLayerGeoJson, projectMapLocationJsons); GeocodeAddressUrl = SitkaRoute <ResultsController> .BuildAbsoluteUrlHttpsFromExpression(x => x.GeocodeAddress(null, null));; }
public IndexViewData(Person currentPerson, NeptunePage neptunePage, MapInitJson ovtaBasedMapInitJson, MapInitJson areaBasedMapInitJson, MapInitJson loadBasedMapInitJson, IEnumerable <Models.TreatmentBMP> treatmentBMPs, List <TrashCaptureStatusType> trashCaptureStatusTypes, List <Models.Parcel> parcels, List <StormwaterJurisdiction> stormwaterJurisdictions, FeatureCollection geoJsonForJurisdictions) : base(currentPerson, neptunePage) { OVTABasedMapInitJson = ovtaBasedMapInitJson; AreaBasedMapInitJson = areaBasedMapInitJson; LoadBasedMapInitJson = loadBasedMapInitJson; var stormwaterJurisdictionIDs = stormwaterJurisdictions.Select(x => x.StormwaterJurisdictionID).ToList(); StormwaterJurisdictionCQLFilter = currentPerson.GetStormwaterJurisdictionCqlFilter(stormwaterJurisdictionIDs); NegativeStormwaterJurisdictionCQLFilter = currentPerson.GetNegativeStormwaterJurisdictionCqlFilter(stormwaterJurisdictionIDs); JurisdictionSelectList = stormwaterJurisdictions.OrderBy(x => x.GetOrganizationDisplayName()) .ToSelectList(x => x.StormwaterJurisdictionID.ToString(CultureInfo.InvariantCulture), x => x.GetOrganizationDisplayName()); var showDropdown = stormwaterJurisdictions.Count > 1; var currentUserIsAnonymousOrUnassigned = CurrentPerson.IsAnonymousOrUnassigned(); ViewDataForAngular = new ViewDataForAngularClass(ovtaBasedMapInitJson, areaBasedMapInitJson, loadBasedMapInitJson, treatmentBMPs, trashCaptureStatusTypes, parcels, StormwaterJurisdictionCQLFilter, showDropdown, NegativeStormwaterJurisdictionCQLFilter, geoJsonForJurisdictions, currentUserIsAnonymousOrUnassigned); EntityName = "Trash Module"; PageTitle = "Welcome"; AllOVTAsUrl = SitkaRoute <OnlandVisualTrashAssessmentController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Index(), NeptuneWebConfiguration.CanonicalHostName); FindBMPUrl = SitkaRoute <TreatmentBMPController> .BuildAbsoluteUrlHttpsFromExpression(x => x.FindABMP(), NeptuneWebConfiguration.CanonicalHostName); BeginOVTAUrl = SitkaRoute <OnlandVisualTrashAssessmentController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Instructions(null), NeptuneWebConfiguration.CanonicalHostName); AddBMPUrl = SitkaRoute <TreatmentBMPController> .BuildAbsoluteUrlHttpsFromExpression(x => x.New(), NeptuneWebConfiguration.CanonicalHostName); RefreshTguUrl = SitkaRoute <HomeController> .BuildUrlFromExpression(x => x.RefreshTrashGeneratingUnits()); ScoreDescriptionsUrl = SitkaRoute <OnlandVisualTrashAssessmentController> .BuildUrlFromExpression(x => x.ScoreDescriptions()); ProgramOverviewPageContentViewData = new ViewPageContentViewData( NeptunePage.GetNeptunePageByPageType(NeptunePageType.TrashModuleProgramOverview), currentPerson); }
private static IEnumerable <string> GenerateProjectListAsHtmlStrings( IReadOnlyCollection <Project> projects) { var projectsRemaining = projects; var projectListAsHtmlStrings = projectsRemaining.OrderBy(project => project.DisplayName).Select(project => { var projectUrl = SitkaRoute <ProjectController> .BuildAbsoluteUrlHttpsFromExpression(controller => controller.Detail(project)); return($@"<div style=""font-size:smaller""><a href=""{projectUrl}"">{project.ProjectName}</a></div>"); }).ToList(); return(projectListAsHtmlStrings); }
public static void SendApprovalMessage(Project project) { Check.Require(project.ProjectApprovalStatus == ProjectApprovalStatus.Approved, "Need to be in Approved state to send the Approved email!"); var submitterPerson = project.ProposingPerson; var fieldDefinitionLabelProject = FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel(); var subject = $"Your {fieldDefinitionLabelProject} \"{project.GetDisplayName().ToEllipsifiedString(80)}\" was approved!"; var detailUrl = SitkaRoute <ProjectController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Detail(project.ProjectID)); var projectListUrl = SitkaRoute <ProjectController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Index()); var message = $@" <p>Dear {submitterPerson.GetFullNameFirstLast()},</p> <p>The {MultiTenantHelpers.GetToolDisplayName()} {fieldDefinitionLabelProject} submitted on {project.SubmissionDate.ToStringDate()} was approved by {project.ReviewedByPerson.GetFullNameFirstLastAndOrg()}.</p> <p>This {fieldDefinitionLabelProject} is now on the <a href=""{projectListUrl}"">{MultiTenantHelpers.GetToolDisplayName()} {fieldDefinitionLabelProject} List</a> and is visible to the public via the {fieldDefinitionLabelProject} detail page.</p> <p><a href=""{detailUrl}"">View this {fieldDefinitionLabelProject}</a></p> <p>Thank you for using the {MultiTenantHelpers.GetToolDisplayName()}!</p> <p>{$"- {MultiTenantHelpers.GetToolDisplayName()} team"}</p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var emailsToSendTo = new List <string> { submitterPerson.Email }; var emailsToReplyTo = new List <string> { project.ReviewedByPerson.Email }; var primaryContactPerson = project.GetPrimaryContact(); if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { emailsToSendTo.Add(primaryContactPerson.Email); } var contactsWhoCanManageProject = project.GetContactsWhoCanManageProject(); foreach (var contact in contactsWhoCanManageProject) { if (!string.Equals(contact.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase) && (primaryContactPerson == null || !string.Equals(contact.Email, primaryContactPerson.Email, StringComparison.InvariantCultureIgnoreCase))) { emailsToSendTo.Add(contact.Email); } } SendMessageAndLogNotification(project, mailMessage, emailsToSendTo, emailsToReplyTo, project.GetProjectStewardPeople().Select(x => x.Email).ToList(), NotificationType.ProjectUpdateApproved); }
private IEnumerable <string> GenerateProjectListAsHtmlStrings( IReadOnlyCollection <Project> projects) { var projectsRemaining = projects; var tenantCanonicalHostName = FirmaWebConfiguration.GetCanonicalHostForBackgroundJob(TenantID); var projectListAsHtmlStrings = projectsRemaining.OrderBy(project => project.GetDisplayName()).Select(project => { var projectUrl = SitkaRoute <ProjectController> .BuildAbsoluteUrlHttpsFromExpression(controller => controller.Detail(project)); projectUrl = SitkaRoute <ProjectController> .ReplaceHostNameForBackgroundJob(projectUrl, tenantCanonicalHostName); return($@"<div style=""font-size:smaller""><a href=""{projectUrl}"">{project.ProjectName}</a></div>"); }).ToList(); return(projectListAsHtmlStrings); }
public static void SendApprovalMessage(Project project) { Check.Require(project.ProjectApprovalStatus == ProjectApprovalStatus.Approved, "Need to be in Approved state to send the Approved email!"); var submitterPerson = project.ProposingPerson; var subject = $"Your {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} \"{project.DisplayName.ToEllipsifiedString(80)}\" was approved!"; var detailUrl = SitkaRoute <ProjectController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Detail(project.ProjectID)); var projectListUrl = SitkaRoute <ProjectController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Index()); var message = $@" <p>Dear {submitterPerson.FullNameFirstLastAndOrg},</p> <p>The {MultiTenantHelpers.GetToolDisplayName()} {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} submitted on {project.SubmissionDate.ToStringDate()} was approved by {project.ReviewedByPerson.FullNameFirstLastAndOrg}.</p> <p>This {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} is now on the <a href=""{projectListUrl}"">{MultiTenantHelpers.GetToolDisplayName()} {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} List</a> and is visible to the public via the {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} detail page.</p> <p><a href=""{detailUrl}"">View this {Models.FieldDefinition.Project.GetFieldDefinitionLabel()}</a></p> <p>Thank you for using the {MultiTenantHelpers.GetToolDisplayName()}!</p> <p>{$"- {MultiTenantHelpers.GetToolDisplayName()} team"}</p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var emailsToSendTo = new List <string> { submitterPerson.Email }; var emailsToReplyTo = new List <string> { project.ReviewedByPerson.Email }; var primaryContactPerson = project.GetPrimaryContact(); if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { if (string.IsNullOrEmpty(primaryContactPerson.Email)) { Logger.Warn($"Primary Contact is missing email address and will not get an Approval Message. Primary Contact ID:{primaryContactPerson.PersonID} Primary Contact Name:{primaryContactPerson.FullNameFirstLast} Project ID:{project.ProjectID} "); } else { emailsToSendTo.Add(primaryContactPerson.Email); } } SendMessageAndLogNotification(project, mailMessage, emailsToSendTo, emailsToReplyTo, GetProjectStewardPeople(project).Select(x => x.Email).ToList(), NotificationType.ProjectUpdateApproved); }
public ActionResult EditBasics(AgreementPrimaryKey agreementPrimaryKey, AgreementEditViewModel viewModel) { var agreement = agreementPrimaryKey.EntityObject; if (!ModelState.IsValid) { return(AgreementViewEdit(viewModel, CurrentFirmaSession, agreement)); } viewModel.UpdateModelAndSaveChanges(agreement, CurrentFirmaSession, HttpRequestStorage.DatabaseEntities); SetMessageForDisplay($"Agreement {agreement.GetDetailLinkUsingAgreementNumber()} saved."); // They may have edited the Agreement Number, so we need to redirect in case this has happened. string redirectUrl = SitkaRoute <AgreementController> .BuildAbsoluteUrlHttpsFromExpression(x => x.AgreementDetail(viewModel.AgreementNumber)); return(new ModalDialogFormJsonResult(redirectUrl)); }
public static void SendSubmittedMessage(List <Person> peopleToNotify, ProjectUpdateBatch projectUpdateBatch) { Check.Require(projectUpdateBatch.ProjectUpdateState == ProjectUpdateState.Submitted, "Need to be in Submitted state to send the Submitted email!"); var latestProjectUpdateHistorySubmitted = projectUpdateBatch.GetLatestProjectUpdateHistorySubmitted(); var submitterPerson = latestProjectUpdateHistorySubmitted.UpdatePerson; var submitterEmails = new List <string> { submitterPerson.Email }; var primaryContactPerson = projectUpdateBatch.Project.GetPrimaryContact(); if (primaryContactPerson != null && !string.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { submitterEmails.Add(primaryContactPerson.Email); } var contactsWhoCanManageProject = projectUpdateBatch.Project.GetContactsWhoCanManageProject(); foreach (var contact in contactsWhoCanManageProject) { if (!string.Equals(contact.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase) && (primaryContactPerson == null || !string.Equals(contact.Email, primaryContactPerson.Email, StringComparison.InvariantCultureIgnoreCase))) { submitterEmails.Add(contact.Email); } } var emailsToSendTo = peopleToNotify.Select(x => x.Email).ToList(); var subject = $"The update for {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} {projectUpdateBatch.Project.GetDisplayName()} was submitted"; var instructionsUrl = SitkaRoute <ProjectUpdateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Instructions(projectUpdateBatch.Project)); var message = $@" <p>The update for {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} {projectUpdateBatch.Project.GetDisplayName()} on { latestProjectUpdateHistorySubmitted.TransitionDate.ToStringDate() } was just submitted by {submitterPerson.GetFullNameFirstLastAndOrg()}.</p> <p>Please review and Approve or Return it at your earliest convenience.<br /> <a href=""{instructionsUrl}"">View this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} update</a></p> <p>You received this email because you are assigned to receive support notifications within the ProjectFirma tool.</p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; SendMessageAndLogNotificationForProjectUpdateTransition(projectUpdateBatch, mailMessage, emailsToSendTo, submitterEmails, new List <string>(), NotificationType.ProjectUpdateSubmitted); }
/// <summary> /// Call for page with associated NeptunePage /// </summary> protected NeptuneViewData(Person currentPerson, Models.NeptunePage neptunePage, bool isHomePage, NeptuneArea neptuneArea) { NeptunePage = neptunePage; CurrentPerson = currentPerson; NeptuneHomeUrl = SitkaRoute <HomeController> .BuildAbsoluteUrlHttpsFromExpression(c => c.Index(), NeptuneWebConfiguration.CanonicalHostNameRoot); LogInUrl = NeptuneHelpers.GenerateLogInUrlWithReturnUrl(); LogOutUrl = NeptuneHelpers.GenerateLogOutUrlWithReturnUrl(); RequestSupportUrl = SitkaRoute <HelpController> .BuildUrlFromExpression(c => c.Support()); LegalUrl = SitkaRoute <HomeController> .BuildUrlFromExpression(c => c.Legal()); MakeNeptuneMenu(currentPerson); NeptuneNavBarViewData = new NeptuneNavBarViewData(currentPerson, LogInUrl, LogOutUrl, RequestSupportUrl, neptuneArea, isHomePage); ViewPageContentViewData = neptunePage != null ? new ViewPageContentViewData(neptunePage, currentPerson) : null; }
public static void SendReturnedMessage(Project project) { var submitterPerson = project.ProposingPerson; var subject = $@"Your {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} ""{project.DisplayName.ToEllipsifiedString(80)}"" was not approved"; var basicsUrl = SitkaRoute <ProjectCreateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.EditBasics(project.ProjectID)); var message = $@" <p>Dear {submitterPerson.FullNameFirstLast},</p> <p>The {MultiTenantHelpers.GetToolDisplayName()} {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} submitted on {project.SubmissionDate.ToStringDate()} has been returned for further review.</p> <p>The {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} was returned by {project.ReviewedByPerson.FullNameFirstLastAndOrg}. {project.ReviewedByPerson.FirstName} will contact you for additional information before this {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} can move forward.</p> <a href=""{basicsUrl}"">View this {Models.FieldDefinition.Project.GetFieldDefinitionLabel()}</a></p> <p>Thank you for using the {MultiTenantHelpers.GetToolDisplayName()}</p> <p>{$"- {MultiTenantHelpers.GetToolDisplayName()} team"}</p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var emailsToSendTo = new List <string> { submitterPerson.Email }; var primaryContactPerson = project.GetPrimaryContact(); if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { if (string.IsNullOrEmpty(primaryContactPerson.Email)) { Logger.Warn($"Primary Contact is missing email address and will not get a Returned Message. Primary Contact ID:{primaryContactPerson.PersonID} Primary Contact Name:{primaryContactPerson.FullNameFirstLast} Project ID:{project.ProjectID} "); } else { emailsToSendTo.Add(primaryContactPerson.Email); } } var emailsToReplyTo = new List <string> { project.ReviewedByPerson.Email }; var emailsToCc = GetProjectStewardPeople(project).Select(x => x.Email).ToList(); SendMessageAndLogNotification(project, mailMessage, emailsToSendTo, emailsToReplyTo, emailsToCc, NotificationType.ProjectReturned); }
public static void SendSubmittedMessage(Project project) { var submitterPerson = project.ProposingPerson; var subject = $"A {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} was submitted by {submitterPerson.GetFullNameFirstLastAndOrg()}"; var basicsUrl = SitkaRoute <ProjectCreateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.EditBasics(project.ProjectID)); var message = $@" <p>A new {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}, “{project.GetDisplayName()}”, was submitted.</p> <p>The {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} was submitted on {project.ProposingDate.ToStringDate()} by { submitterPerson.GetFullNameFirstLastAndOrg() }.<br /> <p>Please review and Approve or Return it at your earliest convenience.</p> <a href=""{basicsUrl}"">View this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}</a></p> <p>You received this email because you are assigned to receive support notifications within the ProjectFirma tool.</p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var emailsToSendTo = project.GetProjectStewardPeople().Select(x => x.Email).Distinct().ToList(); var emailsToReplyTo = new List <string> { submitterPerson.Email }; var primaryContactPerson = project.PrimaryContactPerson; if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { emailsToReplyTo.Add(primaryContactPerson.Email); } var contactsWhoCanManageProject = project.GetContactsWhoCanManageProject(); foreach (var contact in contactsWhoCanManageProject) { if (!string.Equals(contact.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase) && (primaryContactPerson == null || !string.Equals(contact.Email, primaryContactPerson.Email, StringComparison.InvariantCultureIgnoreCase))) { emailsToReplyTo.Add(contact.Email); } } var emailsToCc = new List <string>(); SendMessageAndLogNotification(project, mailMessage, emailsToSendTo, emailsToReplyTo, emailsToCc, NotificationType.ProjectSubmitted); }
public static void SendSubmittedMessage(Project project) { var submitterPerson = project.ProposingPerson; var subject = $"A {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} was submitted by {submitterPerson.FullNameFirstLastAndOrg}"; var basicsUrl = SitkaRoute <ProjectCreateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.EditBasics(project.ProjectID)); var message = $@" <p>A new {Models.FieldDefinition.Project.GetFieldDefinitionLabel()}, “{project.DisplayName}”, was submitted.</p> <p>The {Models.FieldDefinition.Project.GetFieldDefinitionLabel()} was submitted on {project.ProposingDate.ToStringDate()} by { submitterPerson.FullNameFirstLastAndOrg }.<br /> <p>Please review and Approve or Return it at your earliest convenience.</p> <a href=""{basicsUrl}"">View this {Models.FieldDefinition.Project.GetFieldDefinitionLabel()}</a></p> <p>You received this email because you are assigned to receive support notifications within the ProjectFirma tool.</p> "; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var emailsToSendTo = GetProjectStewardPeople(project).Select(x => x.Email).Distinct().ToList(); var emailsToReplyTo = new List <string> { submitterPerson.Email }; var primaryContactPerson = project.GetPrimaryContact(); if (primaryContactPerson != null && !string.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { if (string.IsNullOrEmpty(primaryContactPerson.Email)) { Logger.Warn($"Primary Contact is missing email address and will not get a Submitted Message. Primary Contact ID:{primaryContactPerson.PersonID} Primary Contact Name:{primaryContactPerson.FullNameFirstLast} Project ID:{project.ProjectID} "); } else { emailsToReplyTo.Add(primaryContactPerson.Email); } } var emailsToCc = new List <string>(); SendMessageAndLogNotification(project, mailMessage, emailsToSendTo, emailsToReplyTo, emailsToCc, NotificationType.ProjectSubmitted); }
/// <summary> /// Function required by <see cref="OwinStartupAttribute"/> /// </summary> public void Configuration(IAppBuilder app) { SitkaHttpApplication.Logger.Info("Owin Startup"); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = "Cookies", CookieDomain = CookieDomain, CookieManager = new Microsoft.Owin.Host.SystemWeb.SystemWebChunkingCookieManager(), CookieName = $"{NeptuneWebConfiguration.KeystoneOpenIDClientId}_{NeptuneWebConfiguration.NeptuneEnvironment.NeptuneEnvironmentType}" }); //Needed (at least in development) to allow Neptune to talk to upgraded keystone ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; //Most of the new openID for mvc pieces came from here https://www.scottbrady91.com/ASPNET/Refreshing-your-Legacy-ASPNET-IdentityServer-Client-Applications app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = NeptuneWebConfiguration.KeystoneOpenIDClientId, Authority = NeptuneWebConfiguration.KeystoneOpenIDUrl, RedirectUri = SitkaRoute <AccountController> .BuildAbsoluteUrlHttpsFromExpression(c => c.LogOn(), NeptuneWebConfiguration.CanonicalHostNameRoot), // this has to match the keystone client redirect uri PostLogoutRedirectUri = $"https://{NeptuneWebConfiguration.CanonicalHostNameRoot}/", // OpenID is super picky about this; url must match what Keystone has EXACTLY (Trailing slash and all) ResponseType = "code", Scope = "openid profile offline_access keystone", UseTokenLifetime = false, SignInAsAuthenticationType = "Cookies", //ClientSecret = NeptuneWebConfiguration.KeystoneOpenIDClientSecret, CallbackPath = new PathString("/Account/LogOn"), RequireHttpsMetadata = false, RedeemCode = true, SaveTokens = true, ResponseMode = "query", Notifications = new OpenIdConnectAuthenticationNotifications { AuthenticationFailed = (context) => { if ((context.Exception.Message.StartsWith("OICE_20004") || context.Exception.Message.Contains("IDX10311"))) { context.SkipToNextMiddleware(); return(Task.FromResult(0)); } return(Task.FromResult(0)); }, SecurityTokenValidated = n => { var claimsIdentity = n.AuthenticationTicket.Identity; claimsIdentity.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken)); if (n.ProtocolMessage.Code != null) { claimsIdentity.AddClaim(new Claim("code", n.ProtocolMessage.Code)); } if (n.ProtocolMessage.AccessToken != null) { claimsIdentity.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken)); } //map name claim to default name type claimsIdentity.AddClaim(new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", claimsIdentity.FindFirst(KeystoneOpenIDClaimTypes.Name).Value.ToString())); if (claimsIdentity.IsAuthenticated) // we have a token and we can determine the person. { KeystoneOpenIDUtilities.OpenIDClaimHandler(SyncLocalAccountStore, claimsIdentity); } return(Task.FromResult(0)); }, RedirectToIdentityProvider = n => { if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Authentication) { // generate code verifier and code challenge var codeVerifier = CryptoRandom.CreateUniqueId(32); string codeChallenge; using (var sha256 = SHA256.Create()) { var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier)); codeChallenge = Base64Url.Encode(challengeBytes); } // set code_challenge parameter on authorization request n.ProtocolMessage.SetParameter("code_challenge", codeChallenge); n.ProtocolMessage.SetParameter("code_challenge_method", "S256"); // remember code verifier in cookie (adapted from OWIN nonce cookie) // see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L85 RememberCodeVerifier(n, codeVerifier); } //https://identityserver.github.io/Documentation/docsv2/overview/mvcGettingStarted.html#adding-logout if (n.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnect .OpenIdConnectRequestType.Logout) { var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token"); if (idTokenHint != null) { n.ProtocolMessage.IdTokenHint = idTokenHint.Value; } } return(Task.CompletedTask); }, AuthorizationCodeReceived = n => { // get code verifier from cookie // see: https://github.com/scottbrady91/Blog-Example-Classes/blob/master/AspNetFrameworkPkce/ScottBrady91.BlogExampleCode.AspNetPkce/Startup.cs#L102 var codeVerifier = RetrieveCodeVerifier(n); // attach code_verifier on token request n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier); return(Task.CompletedTask); } } }); ScheduledBackgroundJobBootstrapper.ConfigureHangfireAndScheduledBackgroundJobs(app); }
public static void SendReturnedMessage(List <Person> peopleToCc, ProjectUpdateBatch projectUpdateBatch) { Check.Require(projectUpdateBatch.ProjectUpdateState == ProjectUpdateState.Returned, "Need to be in Returned state to send the Returned email!"); var latestProjectUpdateHistorySubmitted = projectUpdateBatch.GetLatestProjectUpdateHistorySubmitted(); var submitterPerson = latestProjectUpdateHistorySubmitted.UpdatePerson; var emailsToSendTo = new List <string> { submitterPerson.Email }; var personNames = submitterPerson.GetFullNameFirstLast(); var primaryContactPerson = projectUpdateBatch.Project.GetPrimaryContact(); if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { emailsToSendTo.Add(primaryContactPerson.Email); personNames += $" and {primaryContactPerson.GetFullNameFirstLast()}"; } var contactsWhoCanManageProject = projectUpdateBatch.Project.GetContactsWhoCanManageProject(); foreach (var contact in contactsWhoCanManageProject) { if (!string.Equals(contact.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase) && (primaryContactPerson == null || !string.Equals(contact.Email, primaryContactPerson.Email, StringComparison.InvariantCultureIgnoreCase))) { emailsToSendTo.Add(contact.Email); personNames += $" and {contact.GetFullNameFirstLast()}"; } } var returnerPerson = projectUpdateBatch.GetLatestProjectUpdateHistoryReturned().UpdatePerson; var instructionsUrl = SitkaRoute <ProjectUpdateController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Instructions(projectUpdateBatch.Project)); var message = $@" Dear {personNames}, <p> The update submitted for {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} { projectUpdateBatch.Project.GetDisplayName() } on {latestProjectUpdateHistorySubmitted.TransitionDate.ToStringDate()} has been returned by { returnerPerson.GetFullNameFirstLastAndOrg() }. </p> <p> <a href=""{instructionsUrl}"">View this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} update</a> </p> <p> Please review this update and address the comments that { returnerPerson.FirstName } left for you. If you have questions, please email: {returnerPerson.Email} </p> Thank you,<br /> {$"- {MultiTenantHelpers.GetToolDisplayName()} team"} "; var subject = $"The update for {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} {projectUpdateBatch.Project.GetDisplayName()} has been returned - please review and re-submit"; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; SendMessageAndLogNotificationForProjectUpdateTransition(projectUpdateBatch, mailMessage, emailsToSendTo, new List <string> { returnerPerson.Email }, peopleToCc.Select(x => x.Email).ToList(), NotificationType.ProjectUpdateReturned); }
public ViewResult ProjectMap() { List <int> filterValues; ProjectLocationFilterType projectLocationFilterType; ProjectColorByType colorByValue; var currentPersonCanViewProposals = CurrentFirmaSession.CanViewProposals(); if (!String.IsNullOrEmpty(Request.QueryString[ProjectMapCustomization.FilterByQueryStringParameter])) { projectLocationFilterType = ProjectLocationFilterType.ToType(Request .QueryString[ProjectMapCustomization.FilterByQueryStringParameter] .ParseAsEnum <ProjectLocationFilterTypeEnum>()); } else { projectLocationFilterType = ProjectMapCustomization.DefaultLocationFilterType; } if (!String.IsNullOrEmpty(Request.QueryString[ProjectMapCustomization.FilterValuesQueryStringParameter])) { var filterValuesAsString = Request.QueryString[ProjectMapCustomization.FilterValuesQueryStringParameter] .Split(','); filterValues = filterValuesAsString.Select(Int32.Parse).ToList(); } else { filterValues = GetDefaultFilterValuesForFilterType(projectLocationFilterType.ToEnum, currentPersonCanViewProposals); } if (!String.IsNullOrEmpty(Request.QueryString[ProjectMapCustomization.ColorByQueryStringParameter])) { colorByValue = ProjectColorByType.ToType(Request .QueryString[ProjectMapCustomization.ColorByQueryStringParameter] .ParseAsEnum <ProjectColorByTypeEnum>()); } else { colorByValue = ProjectMapCustomization.DefaultColorByType; } var firmaPage = FirmaPageTypeEnum.ProjectMap.GetFirmaPage(); var projectsToShow = ProjectMapCustomization.ProjectsForMap(currentPersonCanViewProposals, CurrentFirmaSession); var initialCustomization = new ProjectMapCustomization(projectLocationFilterType, filterValues, colorByValue); var projectLocationsLayerGeoJson = new LayerGeoJson($"{FieldDefinitionEnum.ProjectLocation.ToType().GetFieldDefinitionLabel()}", projectsToShow.MappedPointsToGeoJsonFeatureCollection(false, true, true), "red", 1, LayerInitialVisibility.LayerInitialVisibilityEnum.Show); var projectLocationsMapInitJson = new ProjectLocationsMapInitJson(projectLocationsLayerGeoJson, initialCustomization, "ProjectLocationsMap", true); // Add Organization Type boundaries according to configuration projectLocationsMapInitJson.Layers.AddRange(HttpRequestStorage.DatabaseEntities.Organizations.GetConfiguredBoundaryLayersGeoJson()); var projectLocationsMapViewData = new ProjectLocationsMapViewData(projectLocationsMapInitJson.MapDivID, null, MultiTenantHelpers.GetTopLevelTaxonomyTiers(), currentPersonCanViewProposals, true); var projectLocationFilterTypesAndValues = CreateProjectLocationFilterTypesAndValuesDictionary(currentPersonCanViewProposals); var projectLocationsUrl = SitkaRoute <ResultsController> .BuildAbsoluteUrlHttpsFromExpression(x => x.ProjectMap()); var filteredProjectsWithLocationAreasUrl = SitkaRoute <ResultsController> .BuildUrlFromExpression(x => x.FilteredProjectsWithLocationAreas(null)); var projectColorByTypes = new List <ProjectColorByType> { ProjectColorByType.ProjectStage }; if (MultiTenantHelpers.IsTaxonomyLevelTrunk()) { projectColorByTypes.Add(ProjectColorByType.TaxonomyTrunk); } else if (MultiTenantHelpers.IsTaxonomyLevelBranch()) { projectColorByTypes.Add(ProjectColorByType.TaxonomyBranch); } var viewData = new ProjectMapViewData(CurrentFirmaSession, firmaPage, projectLocationsMapInitJson, projectLocationsMapViewData, projectLocationFilterTypesAndValues, projectLocationsUrl, filteredProjectsWithLocationAreasUrl, projectColorByTypes, ProjectColorByType.ProjectStage.GetDisplayNameFieldDefinition()); return(RazorView <ProjectMap, ProjectMapViewData>(viewData)); }
public ViewResult ProjectMap() { List <int> filterValues; ProjectLocationFilterType projectLocationFilterType; ProjectColorByType colorByValue; var currentPersonCanViewProposals = CurrentPerson.CanViewProposals; if (!String.IsNullOrEmpty(Request.QueryString[ProjectMapCustomization.FilterByQueryStringParameter])) { projectLocationFilterType = ProjectLocationFilterType.ToType(Request .QueryString[ProjectMapCustomization.FilterByQueryStringParameter] .ParseAsEnum <ProjectLocationFilterTypeEnum>()); } else { projectLocationFilterType = ProjectMapCustomization.DefaultLocationFilterType; } if (!String.IsNullOrEmpty(Request.QueryString[ProjectMapCustomization.FilterValuesQueryStringParameter])) { var filterValuesAsString = Request.QueryString[ProjectMapCustomization.FilterValuesQueryStringParameter] .Split(','); filterValues = filterValuesAsString.Select(Int32.Parse).ToList(); } else { filterValues = ProjectMapCustomization.GetDefaultLocationFilterValues(currentPersonCanViewProposals); } if (!String.IsNullOrEmpty(Request.QueryString[ProjectMapCustomization.ColorByQueryStringParameter])) { colorByValue = ProjectColorByType.ToType(Request .QueryString[ProjectMapCustomization.ColorByQueryStringParameter] .ParseAsEnum <ProjectColorByTypeEnum>()); } else { colorByValue = ProjectMapCustomization.DefaultColorByType; } var firmaPage = FirmaPage.GetFirmaPageByPageType(FirmaPageType.ProjectMap); var projectsToShow = ProjectMapCustomization.ProjectsForMap(CurrentPerson); var initialCustomization = new ProjectMapCustomization(projectLocationFilterType, filterValues, colorByValue); var projectLocationsLayerGeoJson = new LayerGeoJson($"{FieldDefinition.ProjectLocation.GetFieldDefinitionLabel()}", Project.MappedPointsToGeoJsonFeatureCollection(projectsToShow, true, true), "red", 1, LayerInitialVisibility.Show); var projectLocationsMapInitJson = new ProjectLocationsMapInitJson(projectLocationsLayerGeoJson, initialCustomization, "ProjectLocationsMap"); projectLocationsMapInitJson.Layers.AddRange(HttpRequestStorage.DatabaseEntities.Organizations.GetBoundaryLayerGeoJson()); var interactionEventLayer = HttpRequestStorage.DatabaseEntities.InteractionEvents.GetInteractionEventsLayerGeoJson(); projectLocationsMapInitJson.Layers.Add(interactionEventLayer); projectLocationsMapInitJson.Layers.Add(MapInitJson.GetWashingtonCountyLayer()); projectLocationsMapInitJson.Layers.Add(MapInitJson.GetWashingtonLegislativeDistrictLayer()); var projectLocationsMapViewData = new ProjectLocationsMapViewData(projectLocationsMapInitJson.MapDivID, colorByValue.DisplayName, MultiTenantHelpers.GetTopLevelTaxonomyTiers(), currentPersonCanViewProposals); var projectLocationFilterTypesAndValues = CreateProjectLocationFilterTypesAndValuesDictionary(currentPersonCanViewProposals); var projectLocationsUrl = SitkaRoute <ResultsController> .BuildAbsoluteUrlHttpsFromExpression(x => x.ProjectMap()); var filteredProjectsWithLocationAreasUrl = SitkaRoute <ResultsController> .BuildUrlFromExpression(x => x.FilteredProjectsWithLocationAreas(null)); var projectMapLocationJsons = new List <ProjectMapLocationJson>(); var filteredProjectList = projectsToShow.Where(x1 => x1.HasProjectLocationPoint).Where(x => x.ProjectStage.ShouldShowOnMap()).ToList(); projectMapLocationJsons = filteredProjectList.ToList().Select(p => new ProjectMapLocationJson(p)).ToList(); var viewData = new ProjectMapViewData(CurrentPerson, firmaPage, projectLocationsMapInitJson, projectLocationsMapViewData, projectLocationFilterTypesAndValues, projectLocationsUrl, filteredProjectsWithLocationAreasUrl, projectMapLocationJsons); return(RazorView <ProjectMap, ProjectMapViewData>(viewData)); }
private static void SendExistingKeystoneUserCreatedMessage(Person person, Person currentPerson) { var toolDisplayName = MultiTenantHelpers.GetToolDisplayName(); var subject = $"Invitation to {toolDisplayName}"; var message = $@" <div style='font-size: 12px; font-family: Arial'> Welcome {person.FirstName}, <p> You have been invited by a colleague, {currentPerson.GetFullNameFirstLast()}, to check out <a href=""{SitkaRoute<HomeController>.BuildAbsoluteUrlHttpsFromExpression(x => x.Index())}\"">{toolDisplayName}</a>. </p> <p> Because you have logged into other systems that use the same log in service (Keystone) that {toolDisplayName} uses, you already have an account, but it needs to be activated for {toolDisplayName}. </p> <p> When you have a moment, please activate your account by logging in: </p> <strong>Log in here:</strong> <a href=""{FirmaHelpers.GenerateAbsoluteLogInUrl()}"">{toolDisplayName}</a><br /> <strong>Your user name is:</strong> {person.LoginName}<br /> <p> If you don't remember your password, you will be able to reset it from the link above. </p> <p> Sincerely,<br /> The {toolDisplayName} team<br/><br/><img src=""cid:tool-logo"" width=""160"" /> </p>"; var mailMessage = new MailMessage { From = new MailAddress(FirmaWebConfiguration.DoNotReplyEmail), Subject = subject, Body = message, IsBodyHtml = true }; var tenantAttribute = MultiTenantHelpers.GetTenantAttributeFromCache(); var toolLogo = tenantAttribute.TenantSquareLogoFileResourceInfo ?? tenantAttribute.TenantBannerLogoFileResourceInfo; var htmlView = AlternateView.CreateAlternateViewFromString(message, null, "text/html"); htmlView.LinkedResources.Add( new LinkedResource(new MemoryStream(toolLogo.FileResourceData.Data), "img/jpeg") { ContentId = "tool-logo" }); mailMessage.AlternateViews.Add(htmlView); mailMessage.ReplyToList.Add(currentPerson.Email); mailMessage.To.Add(person.Email); SitkaSmtpClient.Send(mailMessage); }
public static void SendApprovalMessage(List <Person> peopleToCc, ProjectUpdateBatch projectUpdateBatch) { Check.Require(projectUpdateBatch.ProjectUpdateState == ProjectUpdateState.Approved, "Need to be in Approved state to send the Approved email!"); var latestProjectUpdateHistorySubmitted = projectUpdateBatch.GetLatestProjectUpdateHistorySubmitted(); var submitterPerson = latestProjectUpdateHistorySubmitted.UpdatePerson; var emailsToSendTo = new List <string> { submitterPerson.Email }; var personNames = submitterPerson.GetFullNameFirstLast(); var primaryContactPerson = projectUpdateBatch.Project.GetPrimaryContact(); if (primaryContactPerson != null && !String.Equals(primaryContactPerson.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase)) { emailsToSendTo.Add(primaryContactPerson.Email); personNames += $" and {primaryContactPerson.GetFullNameFirstLast()}"; } var contactsWhoCanManageProject = projectUpdateBatch.Project.GetContactsWhoCanManageProject(); foreach (var contact in contactsWhoCanManageProject) { if (!string.Equals(contact.Email, submitterPerson.Email, StringComparison.InvariantCultureIgnoreCase) && (primaryContactPerson == null || !string.Equals(contact.Email, primaryContactPerson.Email, StringComparison.InvariantCultureIgnoreCase))) { emailsToSendTo.Add(contact.Email); personNames += $" and {contact.GetFullNameFirstLast()}"; } } var approverPerson = projectUpdateBatch.LastUpdatePerson; var detailUrl = SitkaRoute <ProjectController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Detail(projectUpdateBatch.Project)); var message = $@" Dear {personNames}, <p> The update submitted for {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} {projectUpdateBatch.Project.GetDisplayName()} on { latestProjectUpdateHistorySubmitted.TransitionDate.ToStringDate() } was approved by {approverPerson.GetFullNameFirstLastAndOrg()}. </p> <p> There is no action for you to take - this is simply a notification email. The updates for this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} are now visible to the general public on this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}'s detail page: </p> <p> <a href=""{detailUrl}"">View this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}</a> </p> Thank you for keeping your {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} information and accomplishments up to date!<br /> {$"- {MultiTenantHelpers.GetToolDisplayName()} team"}<br/><br/><img src=""cid:tool-logo"" width=""160"" /> "; var subject = $"The update for {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} {projectUpdateBatch.Project.GetDisplayName()} was approved"; var mailMessage = new MailMessage { Subject = subject, Body = message, IsBodyHtml = true }; var tenantAttribute = MultiTenantHelpers.GetTenantAttributeFromCache(); var toolLogo = tenantAttribute.TenantSquareLogoFileResourceInfo ?? tenantAttribute.TenantBannerLogoFileResourceInfo; var htmlView = AlternateView.CreateAlternateViewFromString(message, null, "text/html"); htmlView.LinkedResources.Add( new LinkedResource(new MemoryStream(toolLogo.FileResourceData.Data), "img/jpeg") { ContentId = "tool-logo" }); mailMessage.AlternateViews.Add(htmlView); SendMessageAndLogNotificationForProjectUpdateTransition(projectUpdateBatch, mailMessage, emailsToSendTo, new List <string> { approverPerson.Email }, peopleToCc.Select(x => x.Email).ToList(), NotificationType.ProjectUpdateApproved); }
private static void SendExistingKeystoneUserCreatedMessage(Person person, Person currentPerson) { var toolDisplayName = MultiTenantHelpers.GetToolDisplayName(); var subject = $"Invitation to {toolDisplayName}"; var message = $@" <div style='font-size: 12px; font-family: Arial'> Welcome {person.FirstName}, <p> You have been invited by a colleague, {currentPerson.GetFullNameFirstLast()}, to check out <a href=""{SitkaRoute<HomeController>.BuildAbsoluteUrlHttpsFromExpression(x => x.Index())}\"">{toolDisplayName}</a>. </p> <p> Because you have logged into other systems that use the same log in service (Keystone) that {toolDisplayName} uses, you already have an account, but it needs to be activated for {toolDisplayName}. </p> <p> When you have a moment, please activate your account by logging in: </p> <strong>Log in here:</strong> <a href=""{FirmaHelpers.GenerateAbsoluteLogInUrl()}"">{toolDisplayName}</a><br /> <strong>Your user name is:</strong> {person.LoginName}<br /> <p> If you don't remember your password, you will be able to reset it from the link above. </p> <p> Sincerely,<br /> The {toolDisplayName} team </p>"; var mailMessage = new MailMessage { From = new MailAddress(FirmaWebConfiguration.DoNotReplyEmail), Subject = subject, Body = message, IsBodyHtml = true }; mailMessage.ReplyToList.Add(currentPerson.Email); mailMessage.To.Add(person.Email); SitkaSmtpClient.Send(mailMessage); }
public void SendMessage(string ipAddress, string userAgent, string currentUrl, SupportRequestType supportRequestType, Project project) { var subject = $"Support Request for Project Firma - {DateTime.Now.ToStringDateTime()}"; var projectSummaryUrl = project == null ? string.Empty : $"<strong>{FieldDefinition.Project.GetFieldDefinitionLabel()}:</strong> <a href=\"{SitkaRoute<ProjectController>.BuildAbsoluteUrlHttpsFromExpression(x => x.Detail(project))}\">{project.DisplayName}</a><br />"; var message = string.Format(@" <div style='font-size: 12px; font-family: Arial'> <strong>{0}</strong><br /> <br /> <strong>From:</strong> {1} - {2}<br /> <strong>Email:</strong> {3}<br /> <strong>Phone:</strong> {4}<br /> {5} <br /> <strong>Subject:</strong> {6}<br /> <br /> <strong>Description:</strong><br /> {7} <br /> <br /> <br /> <div style='font-size: 10px; color: gray'> OTHER DETAILS:<br /> LOGIN: {8}<br /> IP ADDRESS: {9}<br /> USERAGENT: {10}<br /> URL FROM: {11}<br /> <br /> </div> <div>You received this email because you are set up as a point of contact for support - if that's not correct, let us know: {12}</div>. </div> ", subject, RequestPersonName, RequestPersonOrganization ?? "(not provided)", RequestPersonEmail, RequestPersonPhone ?? "(not provided)", projectSummaryUrl, supportRequestType.SupportRequestTypeDisplayName, RequestDescription.HtmlEncodeWithBreaks(), RequestPerson != null ? $"{RequestPerson.FullNameFirstLast} (UserID {RequestPerson.PersonID})" : "(anonymous user)", ipAddress, userAgent, currentUrl, Common.FirmaWebConfiguration.SitkaSupportEmail); // Create Notification var mailMessage = new MailMessage { From = new MailAddress(Common.FirmaWebConfiguration.DoNotReplyEmail), Subject = subject, Body = message, IsBodyHtml = true }; // Reply-To Header mailMessage.ReplyToList.Add(RequestPersonEmail); // TO field SupportRequestType.SetEmailRecipientsOfSupportRequest(mailMessage); SitkaSmtpClient.Send(mailMessage); }
public ActionResult Invite(InviteViewModel viewModel) { var toolDisplayName = MultiTenantHelpers.GetToolDisplayName(); var homeUrl = SitkaRoute <HomeController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Index()); var supportUrl = SitkaRoute <HelpController> .BuildAbsoluteUrlHttpsFromExpression(x => x.RequestSupport()); var tenantAttribute = MultiTenantHelpers.GetTenantAttributeFromCache(); var primaryContactFullName = tenantAttribute.PrimaryContactPerson .GetFullNameFirstLast(); var primaryContactOrganizationName = tenantAttribute.PrimaryContactPerson .Organization.OrganizationName; var primaryContactEmail = tenantAttribute.PrimaryContactPerson.Email; KeystoneService.KeystoneApiResponse <KeystoneService.KeystoneNewUserModel> keystoneNewUserResponse = null; var theSelectedOrganization = HttpRequestStorage.DatabaseEntities.Organizations.GetOrganization(viewModel.OrganizationID); Check.EnsureNotNull(theSelectedOrganization); bool organizationSelectedIsNotUnknownOrg = !theSelectedOrganization.IsUnknown(); if (organizationSelectedIsNotUnknownOrg && theSelectedOrganization.KeystoneOrganizationGuid == null) { // If we pick an Org, it must already be in Keystone, and so the local dbo.Organization must have a valid OrganizationGuid ModelState.AddModelError("OrganizationID", $"Organization is not in Keystone"); } else { var inviteModel = new KeystoneService.KeystoneInviteModel { FirstName = viewModel.FirstName, LastName = viewModel.LastName, Email = viewModel.Email, SiteName = toolDisplayName, Subject = $"Invitation to {toolDisplayName}", WelcomeText = $"You have been invited by {CurrentPerson.GetFullNameFirstLast()} at {CurrentPerson.Organization.OrganizationName} ({CurrentPerson.Email}), to create an account in <a href=\"{homeUrl}\">{toolDisplayName}</a>.", RedirectURL = homeUrl, SupportBlock = $"If you have any questions, please visit our <a href=\"{supportUrl}\">support page</a> or contact {primaryContactFullName} at {primaryContactOrganizationName} ({primaryContactEmail})", OrganizationGuid = theSelectedOrganization.KeystoneOrganizationGuid, SignatureBlock = $"The {toolDisplayName} team" }; var keystoneService = new KeystoneService(HttpRequestStorage.GetHttpContextUserThroughOwin()); keystoneNewUserResponse = keystoneService.Invite(inviteModel); if (keystoneNewUserResponse.StatusCode != HttpStatusCode.OK || keystoneNewUserResponse.Error != null) { ModelState.AddModelError("Email", $"There was a problem inviting the user to Keystone: {keystoneNewUserResponse.Error.Message}."); if (keystoneNewUserResponse.Error.ModelState != null) { foreach (var modelStateKey in keystoneNewUserResponse.Error.ModelState.Keys) { foreach (var err in keystoneNewUserResponse.Error.ModelState[modelStateKey]) { ModelState.AddModelError(modelStateKey, err); } } } } else { // Sanity check - did we get back the same Organization GUID we asked for? // (The GUID could also be null here, for the unknown org, but in that case we'll also get back null so this check is still valid.) var keystoneUserTmp = keystoneNewUserResponse.Payload.Claims; if (keystoneUserTmp.OrganizationGuid != inviteModel.OrganizationGuid) { string errorMessage = $"There was a problem with the Keystone Organization GUID Invited:{inviteModel.OrganizationGuid} Received back: {keystoneUserTmp.OrganizationGuid}. Please contact Sitka for assistance."; _logger.Error(errorMessage); ModelState.AddModelError("OrganizationID", errorMessage); } } } if (!ModelState.IsValid) { return(ViewInvite(viewModel)); } var keystoneUser = keystoneNewUserResponse.Payload.Claims; var existingUser = HttpRequestStorage.DatabaseEntities.People.GetPersonByPersonGuid(keystoneUser.UserGuid); if (existingUser != null) { SetMessageForDisplay($"{existingUser.GetFullNameFirstLastAndOrgAsUrl(CurrentFirmaSession)} already has an account.</a>."); return(RedirectToAction(new SitkaRoute <UserController>(x => x.Detail(existingUser)))); } var newUser = CreateNewFirmaPerson(keystoneUser, keystoneUser.OrganizationGuid); HttpRequestStorage.DatabaseEntities.SaveChanges(); newUser.RoleID = Role.Normal.RoleID; HttpRequestStorage.DatabaseEntities.SaveChanges(); if (!viewModel.DoNotSendInviteEmailIfExisting && !keystoneNewUserResponse.Payload.Created) { SendExistingKeystoneUserCreatedMessage(newUser, CurrentPerson); } SetMessageForDisplay( $"{newUser.GetFullNameFirstLastAndOrgAsUrl(CurrentFirmaSession)} successfully added. You may want to assign them a role</a>."); return(RedirectToAction(new SitkaRoute <UserController>(x => x.Detail(newUser)))); }
public ActionResult Invite(InviteViewModel viewModel) { var toolDisplayName = "Orange County Stormwater Tools"; var homeUrl = SitkaRoute <HomeController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Index(), NeptuneWebConfiguration.CanonicalHostNameRoot); var loginUrl = SitkaRoute <AccountController> .BuildAbsoluteUrlHttpsFromExpression(x => x.LogOn(), NeptuneWebConfiguration.CanonicalHostName); var supportUrl = SitkaRoute <HelpController> .BuildAbsoluteUrlHttpsFromExpression(x => x.Support(), NeptuneWebConfiguration.CanonicalHostNameRoot); var inviteModel = new KeystoneService.KeystoneInviteModel { FirstName = viewModel.FirstName, LastName = viewModel.LastName, Email = viewModel.Email, SiteName = toolDisplayName, Subject = $"Invitation to the {toolDisplayName}", WelcomeText = $"You have been invited by a colleague to create an account in the <a href=\"{homeUrl}\">{toolDisplayName}</a>. The {toolDisplayName} application is a collaborative effort of Orange County Public Works, MS4 Permittees, and other organizations.", RedirectURL = loginUrl, SupportBlock = $"If you have any questions, please visit our <a href=\"{supportUrl}\">support page</a>", OrganizationGuid = viewModel.OrganizationGuid, SignatureBlock = $"The {toolDisplayName} team" }; var keystoneService = new KeystoneService(HttpRequestStorage.GetHttpContextUserThroughOwin()); var response = keystoneService.Invite(inviteModel); if (response.StatusCode != HttpStatusCode.OK || response.Error != null) { ModelState.AddModelError("Email", $"There was a problem inviting the user to Keystone: {response.Error.Message}."); if (response.Error.ModelState != null) { foreach (var modelStateKey in response.Error.ModelState.Keys) { foreach (var err in response.Error.ModelState[modelStateKey]) { ModelState.AddModelError(modelStateKey, err); } } } } if (!ModelState.IsValid) { return(ViewInvite(viewModel)); } var keystoneUser = response.Payload.Claims; var existingUser = HttpRequestStorage.DatabaseEntities.People.GetPersonByPersonGuid(keystoneUser.UserGuid); if (existingUser != null) { SetMessageForDisplay($"{existingUser.GetFullNameFirstLastAndOrgAsUrl()} already has an account.</a>."); return(RedirectToAction(new SitkaRoute <UserController>(x => x.Detail(existingUser)))); } var setJurisdictions = !CurrentPerson.IsAdministrator(); var newUser = CreateNewFirmaPerson(keystoneUser, keystoneUser.OrganizationGuid); HttpRequestStorage.DatabaseEntities.SaveChanges(); if (setJurisdictions) { foreach (var stormwaterJurisdictionPerson in CurrentPerson.StormwaterJurisdictionPeople) { newUser.StormwaterJurisdictionPeople.Add(new StormwaterJurisdictionPerson(stormwaterJurisdictionPerson.StormwaterJurisdictionID, newUser.PersonID)); } } newUser.RoleID = Role.JurisdictionEditor.RoleID; HttpRequestStorage.DatabaseEntities.SaveChanges(); SetMessageForDisplay( $"{newUser.GetFullNameFirstLastAndOrgAsUrl()} successfully added. You may want to assign them a role</a>."); return(RedirectToAction(new SitkaRoute <UserController>(x => x.Detail(newUser)))); }