public async Task <IOperationResult <ConfirmationRequestData> > ProcessConfigurationChangeRequest(
            string vaultIp,
            string vaultPort,
            string vaultToken)
        {
            if (_lastConfigurationChangeRequestAt.HasValue &&
                _lastConfigurationChangeRequestAt.Value.AddMinutes(MINUTES_BETWEEN_CONFIGURATION_CHANGE_REQUESTS) > DateTime.Now)
            {
                return(OperationResult.UserError <ConfirmationRequestData>($"Please, wait. The interval between configuration requests is: {MINUTES_BETWEEN_CONFIGURATION_CHANGE_REQUESTS}"));
            }
            else
            {
                _lastConfigurationChangeRequestAt = DateTime.Now;
            }

            return(await
                   OperationResult
                   .Try(() => CreateVaultClient(vaultIp, vaultPort, vaultToken))
                   .BindAsync(async(x) => await ReadConfiguration(x))
                   .Bind(candidateProtectedConfiguration =>
            {
                // A new configuration has been read. We set it as a candidate.
                _candidateProtectedConfiguration = candidateProtectedConfiguration;

                // The email is stored in protected form. If it's been set already, we use the current one, otherwise the candidate one
                var requestFields = new[]
                {
                    ConfigurationKey.AdminEmail,
                    ConfigurationKey.SmtpHost,
                    ConfigurationKey.SmtpPort,
                    ConfigurationKey.MailingAccountLogin,
                    ConfigurationKey.MailingAccountPassword
                };

                var actingProtectedConfiguration = _currentProtectedConfiguration.Keys.Intersect(requestFields).Count() == requestFields.Length
                        ? _currentProtectedConfiguration
                        : _candidateProtectedConfiguration;

                // Generate and set the confirmation code parameters
                var confirmationCode = Guid.NewGuid().ToString();
                _confirmationCodeProtected = _dataProtector.Protect(confirmationCode);
                _confirmationCodeIssuedAt = DateTime.Now;

                var requestData = new ConfirmationRequestData
                {
                    ConfirmationCode = confirmationCode,
                    AdminEmail = _dataProtector.Unprotect(actingProtectedConfiguration[ConfigurationKey.AdminEmail]),
                    SmtpHost = _dataProtector.Unprotect(actingProtectedConfiguration[ConfigurationKey.SmtpHost]),
                    SmtpPort = _dataProtector.Unprotect(actingProtectedConfiguration[ConfigurationKey.SmtpPort]),
                    MailingAccountLogin = _dataProtector.Unprotect(actingProtectedConfiguration[ConfigurationKey.MailingAccountLogin]),
                    MailingAccountPassword = _dataProtector.Unprotect(actingProtectedConfiguration[ConfigurationKey.MailingAccountPassword]),
                };
                return OperationResult.Success(requestData);
            }));
        }
Example #2
0
        public IOperationResult SendConfirmCode(ConfirmationRequestData data)
        {
            return(OperationResult.Try(() =>
            {
                if (string.IsNullOrEmpty(data.AdminEmail) ||
                    string.IsNullOrEmpty(data.SmtpHost) ||
                    string.IsNullOrEmpty(data.SmtpPort) ||
                    string.IsNullOrEmpty(data.MailingAccountLogin) ||
                    string.IsNullOrEmpty(data.SmtpPort))
                {
                    return OperationResult.Failure(new Exception("One of necessary configuration parameters is empty"));
                }

                var message = new MimeMessage();

                message.From.Add(new MailboxAddress("Quiz", data.MailingAccountLogin));
                message.To.Add(new MailboxAddress("Quiz", data.AdminEmail));
                message.Subject = "An attempt to change configuration";

                var confirmUrl = string.Format("{0}://{1}/Configuration/Confirm?confirmCode={2}",
                                               _contextAccessor.HttpContext.Request.Scheme,
                                               _contextAccessor.HttpContext.Request.Host,
                                               data.ConfirmationCode);

                message.Body = new TextPart(MimeKit.Text.TextFormat.Html)
                {
                    Text = $"To confirm new configuration visit <a href='{confirmUrl}'>this link</a>"
                };

                using (var client = new SmtpClient())
                {
                    client.ServerCertificateValidationCallback = (s, c, h, e) => true;

                    client.Connect(data.SmtpHost, int.Parse(data.SmtpPort), SecureSocketOptions.SslOnConnect);
                    client.Authenticate(data.MailingAccountLogin, data.MailingAccountPassword);
                    client.Send(message);
                    client.Disconnect(true);
                    return OperationResult.Success();
                }
            }));
        }