public override async Task <SendEmailResult> SendEmailAsync <TTemplate>(string emailAddress,
                                                                                string templateId,
                                                                                TTemplate parameters,
                                                                                bool test)
        {
            // convert the model's public properties to a dictionary
            var mergeParameters = parameters.GetPropertiesDictionary();

            // prefix subject with environment name
            mergeParameters["Environment"] = SharedOptions.IsProduction() ? "" : $"[{SharedOptions.Environment}] ";

            // determine which client to use
            var client = test ? TestClient : ProductionClient;

            // send email
            var response = await client.SendEmailAsync(
                emailAddress,
                templateId,
                mergeParameters,
                Options.ClientReference);

            // get result
            var notification = await client.GetNotificationByIdAsync(response.id);

            return(new SendEmailResult
            {
                Status = notification.status,
                Server = "Gov Notify",
                ServerUsername = Options.ClientReference,
                EmailAddress = emailAddress,
                EmailSubject = notification.subject
            });
        }
Exemple #2
0
        public PagedResult<EmployerRecord> LoadSearch(string searchText)
        {
            var lastSearchText = _Session["LastPrivateSearchText"] as string;
            var remoteTotal = _Session["LastPrivateSearchRemoteTotal"].ToInt32();

            PagedResult<EmployerRecord> result = null;

            if (!SharedOptions.IsProduction()
                && _httpContextAccessor.HttpContext != null
                && _httpContextAccessor.HttpContext.Request.Query["fail"].ToBoolean())
            {
                ClearSearch();
            }
            else if (remoteTotal == -1 || string.IsNullOrWhiteSpace(lastSearchText) || searchText != lastSearchText)
            {
                ClearSearch();
            }
            else
            {
                result = _Session.Get<PagedResult<EmployerRecord>>("LastPrivateSearchResults");
                if (result == null) result = new PagedResult<EmployerRecord>();
            }

            return result;
        }
        private bool CheckPasswordBasedOnHashingAlgorithm(User user, string password)
        {
            switch (user.HashingAlgorithm)
            {
            case HashingAlgorithm.Unhashed:
                if (SharedOptions.IsProduction())
                {
                    break;
                }
                return(user.PasswordHash == password);

            case HashingAlgorithm.SHA512:
                return(user.PasswordHash == Crypto.GetSHA512Checksum(password));

            case HashingAlgorithm.PBKDF2:
                return(user.PasswordHash == Crypto.GetPBKDF2(password, Convert.FromBase64String(user.Salt)));

            case HashingAlgorithm.PBKDF2AppliedToSHA512:
                return(user.PasswordHash == Crypto.GetPBKDF2(Crypto.GetSHA512Checksum(password),
                                                             Convert.FromBase64String(user.Salt)));

            case HashingAlgorithm.Unknown:
                break;

            default:
                throw new InvalidEnumArgumentException($"Invalid enum argument: {user.HashingAlgorithm}");
            }

            throw new InvalidOperationException($"Hashing algorithm should not be {user.HashingAlgorithm}");
        }
Exemple #4
0
        public IEnumerable <Client> Get()
        {
            if ((_sharedOptions.IsProduction() || _sharedOptions.IsPreProduction()) &&
                _sharedOptions.AuthSecret.EqualsI("secret", "", null))
            {
                throw new Exception(
                          "Invalid ClientSecret for IdentityServer. You must set 'AuthSecret' to a unique key");
            }

            return(new[]
            {
                new Client
                {
                    ClientName = "Modern Slavery reporting service",
                    ClientId = "ModernSlaveryServiceWebsite",
                    ClientSecrets = new List <Secret> {
                        new Secret(_sharedOptions.AuthSecret.GetSHA256Checksum())
                    },
                    ClientUri = _sharedOptions.SiteAuthority,
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser = true,
                    RequireConsent = false,
                    RedirectUris =
                        new List <string>
                    {
                        _sharedOptions.SiteAuthority,
                        _sharedOptions.SiteAuthority + "signin-oidc",
                        _sharedOptions.SiteAuthority + "manage-organisations",
                        _sharedOptions.DoneUrl
                    },
                    PostLogoutRedirectUris =
                        new List <string>
                    {
                        _sharedOptions.SiteAuthority,
                        _sharedOptions.SiteAuthority + "signout-callback-oidc",
                        _sharedOptions.SiteAuthority + "manage-organisations",
                        _sharedOptions.SiteAuthority + "manage-account/complete-change-email",
                        _sharedOptions.SiteAuthority + "manage-account/close-account-completed",
                        _sharedOptions.DoneUrl
                    },
                    AllowedScopes =
                        new List <string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile, "roles"
                    },
                    Properties = new Dictionary <string, string> {
                        { "AutomaticRedirectAfterSignOut", "true" }
                    }
                }
            });
        }
        public void Register(IDependencyBuilder builder)
        {
            if (string.IsNullOrWhiteSpace(_sharedOptions.GoogleAnalyticsAccountId))
            {
                if (_sharedOptions.IsProduction())
                {
                    throw new ArgumentNullException(nameof(_sharedOptions.GoogleAnalyticsAccountId));
                }

                builder.Autofac.RegisterType <FakeWebTracker>().As <IWebTracker>().SingleInstance();
                return;
            }

            //Add a dedicated httpclient for Google Analytics tracking with exponential retry policy
            builder.Services.AddHttpClient <IWebTracker, GoogleAnalyticsTracker>(nameof(IWebTracker), client =>
            {
                client.BaseAddress = GoogleAnalyticsTracker.BaseUri;
                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.ConnectionClose = false;
                ServicePointManager.FindServicePoint(client.BaseAddress).ConnectionLeaseTimeout = 60 * 1000;
            })
            .SetHandlerLifetime(TimeSpan.FromMinutes(10))
            .AddPolicyHandler(
                //see https://developers.google.com/analytics/devguides/config/mgmt/v3/errors
                HttpPolicyExtensions
                .HandleTransientHttpError()
                .WaitAndRetryAsync(6,
                                   retryAttempt => TimeSpan.FromMilliseconds(new Random().Next(1, 1000)) +
                                   TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));

            //Register WebTracker
            builder.Autofac.RegisterType <GoogleAnalyticsTracker>()
            .As <IWebTracker>()
            .SingleInstance()
            .WithParameter(
                (p, ctx) => p.ParameterType == typeof(HttpClient),
                (p, ctx) => ctx.Resolve <IHttpClientFactory>().CreateClient(nameof(IWebTracker)))
            .WithParameter("trackingId", _sharedOptions.GoogleAnalyticsAccountId);
        }
Exemple #6
0
        public void DeleteAllTestRecords(DateTime?deadline = null)
        {
            if (SharedOptions.IsProduction())
            {
                throw new Exception("Attempt to delete all test data from production environment");
            }

            if (string.IsNullOrWhiteSpace(SharedOptions.TestPrefix))
            {
                throw new ArgumentNullException(nameof(SharedOptions.TestPrefix));
            }

            if (deadline == null || deadline.Value == DateTime.MinValue)
            {
                ExecuteSqlCommand(
                    $"UPDATE UO SET AddressId=null FROM UserOrganisations UO WITH (ROWLOCK) JOIN organisations O ON O.OrganisationId=UO.OrganisationId where O.OrganisationName like '{SharedOptions.TestPrefix}%'");
                ExecuteSqlCommand(
                    $"UPDATE UO SET AddressId=null FROM UserOrganisations UO WITH (ROWLOCK) JOIN Users U ON U.UserId=UO.UserId where U.Firstname like '{SharedOptions.TestPrefix}%'");
                ExecuteSqlCommand(
                    $"UPDATE Organisations WITH (ROWLOCK) SET LatestAddressId=null, LatestRegistration_OrganisationId=null,LatestRegistration_UserId=null,LatestReturnId=null,LatestScopeId=null where OrganisationName like '{SharedOptions.TestPrefix}%'");
                ExecuteSqlCommand($"DELETE Users WITH (ROWLOCK) where Firstname like '{SharedOptions.TestPrefix}%'");
                ExecuteSqlCommand(
                    $"DELETE Organisations WITH (ROWLOCK) where OrganisationName like '{SharedOptions.TestPrefix}%'");
            }
            else
            {
                var dl = deadline.Value.ToString("yyyy-MM-dd HH:mm:ss");
                ExecuteSqlCommand(
                    $"UPDATE UO SET AddressId=null FROM UserOrganisations UO WITH (ROWLOCK) JOIN organisations O ON O.OrganisationId=UO.OrganisationId where O.OrganisationName like '{SharedOptions.TestPrefix}%' AND UO.Created<'{dl}'");
                ExecuteSqlCommand(
                    $"UPDATE UO SET AddressId=null FROM UserOrganisations UO WITH (ROWLOCK) JOIN Users U ON U.UserId=UO.UserId where U.Firstname like '{SharedOptions.TestPrefix}%' AND UO.Created<'{dl}'");
                ExecuteSqlCommand(
                    $"UPDATE Organisations WITH (ROWLOCK) SET LatestAddressId=null, LatestRegistration_OrganisationId=null,LatestRegistration_UserId=null,LatestReturnId=null,LatestScopeId=null where OrganisationName like '{SharedOptions.TestPrefix}%' AND Created<'{dl}'");
                ExecuteSqlCommand(
                    $"DELETE Users WITH (ROWLOCK) where Firstname like '{SharedOptions.TestPrefix}%' AND Created<'{dl}'");
                ExecuteSqlCommand(
                    $"DELETE Organisations WITH (ROWLOCK) where OrganisationName like '{SharedOptions.TestPrefix}%' AND Created<'{dl}'");
            }
        }
        public async void SendSuccessfulSubmissionEmail(string emailAddress,
                                                        string organisationName,
                                                        string submittedOrUpdated,
                                                        string reportingPeriod,
                                                        string reportLink)
        {
            var personalisation = new Dictionary <string, dynamic>
            {
                { "OrganisationName", organisationName },
                { "SubmittedOrUpdated", submittedOrUpdated },
                { "ReportingPeriod", reportingPeriod },
                { "ReportLink", reportLink },
                { "Environment", SharedOptions.IsProduction() ? "" : $"[{SharedOptions.Environment}] " }
            };

            var notifyEmail = new SendEmailRequest
            {
                EmailAddress    = emailAddress, TemplateId = EmailTemplates.SendSuccessfulSubmissionEmail,
                Personalisation = personalisation
            };

            await AddEmailToQueue(notifyEmail);
        }
Exemple #8
0
        public override async Task <SendEmailResult> SendEmailAsync <TModel>(string emailAddress, string templateId,
                                                                             TModel model, bool test)
        {
            // convert the model's public properties to a dictionary
            var mergeParameters = model.GetPropertiesDictionary();

            // prefix subject with environment name
            mergeParameters["Environment"] = SharedOptions.IsProduction() ? "" : $"[{SharedOptions.Environment}] ";

            // get template
            var emailTemplateInfo = EmailTemplateRepo.GetByTemplateId(templateId);
            var htmlContent       = File.ReadAllText(emailTemplateInfo.FilePath);

            // parse html
            var parser   = new HtmlParser();
            var document = parser.ParseDocument(htmlContent);

            // remove the meta data comments from the document
            var templateMetaData = document.Descendents <IComment>().FirstOrDefault();

            if (templateMetaData == null)
            {
                new NullReferenceException(nameof(templateMetaData));
            }

            templateMetaData.Remove();

            var messageSubject = emailTemplateInfo.EmailSubject;
            var messageHtml    = document.ToHtml();
            var messageText    = document.Text();

            // merge the template parameters
            foreach ((string name, object value) in mergeParameters)
            {
                messageSubject = messageSubject.Replace($"(({name}))", value.ToString());
                messageHtml    = messageHtml.Replace($"(({name}))", value.ToString());
            }

            var smtpServer     = string.IsNullOrWhiteSpace(Options.Server) ? Options.Server2 : Options.Server;
            var smtpServerPort = Options.Port <= 0 ? Options.Port2 : Options.Port;
            var smtpUsername   = string.IsNullOrWhiteSpace(Options.Username) ? Options.Username2 : Options.Username;
            var smtpPassword   = string.IsNullOrWhiteSpace(Options.Password) ? Options.Password2 : Options.Password;

            await Email.QuickSendAsync(
                messageSubject,
                Options.SenderEmail,
                Options.SenderName,
                Options.ReplyEmail,
                emailAddress,
                messageHtml,
                smtpServer,
                smtpUsername,
                smtpPassword,
                smtpServerPort,
                test : test);

            return(new SendEmailResult
            {
                Status = "sent",
                Server = $"{smtpServer}:{smtpServerPort}",
                ServerUsername = smtpUsername,
                EmailAddress = emailAddress,
                EmailSubject = messageSubject,
                EmailMessagePlainText = messageText
            });
        }