protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken)
        {
            string         code;
            string         callbackUrl;
            MailboxAddress address;
            UserPasswordResetRequestedEvent userPasswordResetRequestedEvent;

            switch (evt)
            {
            case UserRegisteredEvent userRegisteredEvent:
                Logs.PayServer.LogInformation(
                    $"A new user just registered {userRegisteredEvent.User.Email} {(userRegisteredEvent.Admin ? "(admin)" : "")}");
                if (!userRegisteredEvent.User.EmailConfirmed && userRegisteredEvent.User.RequiresEmailConfirmation)
                {
                    code = await _userManager.GenerateEmailConfirmationTokenAsync(userRegisteredEvent.User);

                    callbackUrl = _generator.EmailConfirmationLink(userRegisteredEvent.User.Id, code,
                                                                   userRegisteredEvent.RequestUri.Scheme,
                                                                   new HostString(userRegisteredEvent.RequestUri.Host, userRegisteredEvent.RequestUri.Port),
                                                                   userRegisteredEvent.RequestUri.PathAndQuery);
                    userRegisteredEvent.CallbackUrlGenerated?.SetResult(new Uri(callbackUrl));
                    address = userRegisteredEvent.User.GetMailboxAddress();
                    (await _emailSenderFactory.GetEmailSender()).SendEmailConfirmation(address, callbackUrl);
                }
                else if (!await _userManager.HasPasswordAsync(userRegisteredEvent.User))
                {
                    userPasswordResetRequestedEvent = new UserPasswordResetRequestedEvent()
                    {
                        CallbackUrlGenerated = userRegisteredEvent.CallbackUrlGenerated,
                        User       = userRegisteredEvent.User,
                        RequestUri = userRegisteredEvent.RequestUri
                    };
                    goto passwordSetter;
                }
                else
                {
                    userRegisteredEvent.CallbackUrlGenerated?.SetResult(null);
                }

                break;

            case UserPasswordResetRequestedEvent userPasswordResetRequestedEvent2:
                userPasswordResetRequestedEvent = userPasswordResetRequestedEvent2;
passwordSetter:
                code = await _userManager.GeneratePasswordResetTokenAsync(userPasswordResetRequestedEvent.User);

                var newPassword = await _userManager.HasPasswordAsync(userPasswordResetRequestedEvent.User);

                callbackUrl = _generator.ResetPasswordCallbackLink(userPasswordResetRequestedEvent.User.Id, code,
                                                                   userPasswordResetRequestedEvent.RequestUri.Scheme,
                                                                   new HostString(userPasswordResetRequestedEvent.RequestUri.Host,
                                                                                  userPasswordResetRequestedEvent.RequestUri.Port),
                                                                   userPasswordResetRequestedEvent.RequestUri.PathAndQuery);
                userPasswordResetRequestedEvent.CallbackUrlGenerated?.SetResult(new Uri(callbackUrl));
                address = userPasswordResetRequestedEvent.User.GetMailboxAddress();
                (await _emailSenderFactory.GetEmailSender())
                .SendSetPasswordConfirmation(address, callbackUrl, newPassword);
                break;
            }
        }
Beispiel #2
0
        public async Task <IActionResult> ForgotPassword(ForgotPasswordViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = await _userManager.FindByEmailAsync(model.Email);

                if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
                {
                    // Don't reveal that the user does not exist or is not confirmed
                    return(RedirectToAction(nameof(ForgotPasswordConfirmation)));
                }

                // For more information on how to enable account confirmation and password reset please
                // visit https://go.microsoft.com/fwlink/?LinkID=532713
                var code = await _userManager.GeneratePasswordResetTokenAsync(user);

                var callbackUrl = Url.ResetPasswordCallbackLink(user.Id, code, Request.Scheme);
                _EmailSenderFactory.GetEmailSender().SendEmail(model.Email, "Reset Password",
                                                               $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");

                return(RedirectToAction(nameof(ForgotPasswordConfirmation)));
            }

            // If we got this far, something failed, redisplay form
            return(View(model));
        }
        protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken)
        {
            switch (evt)
            {
            case UserRegisteredEvent userRegisteredEvent:
                Logs.PayServer.LogInformation($"A new user just registered {userRegisteredEvent.User.Email} {(userRegisteredEvent.Admin ? "(admin)" : "")}");
                if (!userRegisteredEvent.User.EmailConfirmed && userRegisteredEvent.User.RequiresEmailConfirmation)
                {
                    var code = await _userManager.GenerateEmailConfirmationTokenAsync(userRegisteredEvent.User);

                    var callbackUrl = _generator.EmailConfirmationLink(userRegisteredEvent.User.Id, code, userRegisteredEvent.RequestUri.Scheme, new HostString(userRegisteredEvent.RequestUri.Host, userRegisteredEvent.RequestUri.Port), userRegisteredEvent.RequestUri.PathAndQuery);

                    _emailSenderFactory.GetEmailSender()
                    .SendEmailConfirmation(userRegisteredEvent.User.Email, callbackUrl);
                }
                break;
            }
        }
    protected override async Task ProcessEvent(object evt, CancellationToken cancellationToken)
    {
        if (evt is InvoiceEvent invoiceEvent)
        {
            var type = WebhookSender.GetWebhookEvent(invoiceEvent);
            if (type is null)
            {
                return;
            }

            var store = await _storeRepository.FindStore(invoiceEvent.Invoice.StoreId);


            var blob = store.GetStoreBlob();
            if (blob.EmailRules?.Any() is true)
            {
                var actionableRules = blob.EmailRules.Where(rule => rule.Trigger == type.Type).ToList();
                if (actionableRules.Any())
                {
                    var sender = await _emailSenderFactory.GetEmailSender(invoiceEvent.Invoice.StoreId);

                    foreach (UIStoresController.StoreEmailRule actionableRule in actionableRules)
                    {
                        var recipients = (actionableRule.To?.Split(",", StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>())
                                         .Select(o =>
                        {
                            MailboxAddressValidator.TryParse(o, out var mb);
                            return(mb);
                        })
                                         .Where(o => o != null)
                                         .ToList();
                        if (actionableRule.CustomerEmail &&
                            MailboxAddressValidator.TryParse(invoiceEvent.Invoice.Metadata.BuyerEmail, out var bmb))
                        {
                            recipients.Add(bmb);
                        }
                        var i = GreenfieldInvoiceController.ToModel(invoiceEvent.Invoice, _linkGenerator, null);
                        sender.SendEmail(recipients.ToArray(), null, null, Interpolator(actionableRule.Subject, i),
                                         Interpolator(actionableRule.Body, i));
                    }
                }
            }
        }
    }
Beispiel #5
0
        public async Task <IActionResult> SendEmailFromStore(string storeId,
                                                             [FromBody] SendEmailRequest request)
        {
            var store = HttpContext.GetStoreData();

            if (store == null)
            {
                return(this.CreateAPIError(404, "store-not-found", "The store was not found"));
            }
            var emailSender = await _emailSenderFactory.GetEmailSender(storeId);

            if (emailSender is null)
            {
                return(this.CreateAPIError(404, "smtp-not-configured", "Store does not have an SMTP server configured."));
            }

            emailSender.SendEmail(request.Email, request.Subject, request.Body);
            return(Ok());
        }
        public async Task <IActionResult> SendVerificationEmail(IndexViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return(View(nameof(Index), model));
            }

            var user = await _userManager.GetUserAsync(User);

            if (user == null)
            {
                throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
            }

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);

            var callbackUrl = _linkGenerator.EmailConfirmationLink(user.Id, code, Request.Scheme, Request.Host, Request.PathBase);

            (await _EmailSenderFactory.GetEmailSender()).SendEmailConfirmation(user.GetMailboxAddress(), callbackUrl);
            TempData[WellKnownTempData.SuccessMessage] = "Verification email sent. Please check your email.";
            return(RedirectToAction(nameof(Index)));
        }
Beispiel #7
0
        public async Task <IActionResult> SendVerificationEmail(IndexViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            var user = await _userManager.GetUserAsync(User);

            if (user == null)
            {
                throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
            }

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);

            var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
            var email       = user.Email;

            _EmailSenderFactory.GetEmailSender().SendEmailConfirmation(email, callbackUrl);
            StatusMessage = "Verification email sent. Please check your email.";
            return(RedirectToAction(nameof(Index)));
        }
        public async Task <IActionResult> SendVerificationEmail(IndexViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            var user = await _userManager.GetUserAsync(User);

            if (user == null)
            {
                throw new ApplicationException($"No se puede cargar usuario con ID '{_userManager.GetUserId(User)}'.");
            }

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);

            var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
            var email       = user.Email;

            _EmailSenderFactory.GetEmailSender().SendEmailConfirmation(email, callbackUrl);
            StatusMessage = "El mensaje de verificación ha sido enviado. Por favor revise su correo electrónico.";
            return(RedirectToAction(nameof(Index)));
        }
        public async Task <IActionResult> SendEmailFromStore(string storeId,
                                                             [FromBody] SendEmailRequest request)
        {
            var store = HttpContext.GetStoreData();

            if (store == null)
            {
                return(this.CreateAPIError(404, "store-not-found", "The store was not found"));
            }
            if (!MailboxAddressValidator.TryParse(request.Email, out var to))
            {
                ModelState.AddModelError(nameof(request.Email), "Invalid email");
                return(this.CreateValidationError(ModelState));
            }
            var emailSender = await _emailSenderFactory.GetEmailSender(storeId);

            if (emailSender is null)
            {
                return(this.CreateAPIError(404, "smtp-not-configured", "Store does not have an SMTP server configured."));
            }
            emailSender.SendEmail(to, request.Subject, request.Body);
            return(Ok());
        }
Beispiel #10
0
        void Notify(InvoiceEntity invoice, int?eventCode = null, string name = null)
        {
            CancellationTokenSource cts = new CancellationTokenSource(10000);

            if (!String.IsNullOrEmpty(invoice.NotificationEmail))
            {
                // just extracting most important data for email body, merchant should query API back for full invoice based on Invoice.Id
                var ipn = new
                {
                    invoice.Id,
                    invoice.Status,
                    invoice.StoreId
                };
                // TODO: Consider adding info on ItemDesc and payment info (amount)

                var emailBody = NBitcoin.JsonConverters.Serializer.ToString(ipn);

                _EmailSenderFactory.GetEmailSender(invoice.StoreId).SendEmail(
                    invoice.NotificationEmail,
                    $"BtcPayServer Invoice Notification - ${invoice.StoreId}",
                    emailBody);
            }
            if (string.IsNullOrEmpty(invoice.NotificationURL))
            {
                return;
            }
            var invoiceStr = NBitcoin.JsonConverters.Serializer.ToString(new ScheduledJob()
            {
                TryCount = 0, Invoice = invoice, EventCode = eventCode, Message = name
            });

            if (!string.IsNullOrEmpty(invoice.NotificationURL))
            {
                _JobClient.Schedule(() => NotifyHttp(invoiceStr), TimeSpan.Zero);
            }
        }
Beispiel #11
0
        public async Task <IActionResult> Register(RegisterViewModel model, string returnUrl = null, bool logon = true)
        {
            ViewData["ReturnUrl"]    = returnUrl;
            ViewData["Logon"]        = logon.ToString(CultureInfo.InvariantCulture).ToLowerInvariant();
            ViewData["AllowIsAdmin"] = _Options.AllowAdminRegistration;
            var policies = await _SettingsRepository.GetSettingAsync <PoliciesSettings>() ?? new PoliciesSettings();

            if (policies.LockSubscription && !User.IsInRole(Roles.ServerAdmin))
            {
                return(RedirectToAction(nameof(HomeController.Index), "Home"));
            }
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser {
                    UserName = model.Email, Email = model.Email, RequiresEmailConfirmation = policies.RequiresConfirmedEmail
                };
                var result = await _userManager.CreateAsync(user, model.Password);

                if (result.Succeeded)
                {
                    var admin = await _userManager.GetUsersInRoleAsync(Roles.ServerAdmin);

                    Logs.PayServer.LogInformation($"A new user just registered {user.Email} {(admin.Count == 0 ? "(admin)" : "")}");
                    if (admin.Count == 0 || (model.IsAdmin && _Options.AllowAdminRegistration))
                    {
                        await _RoleManager.CreateAsync(new IdentityRole(Roles.ServerAdmin));

                        await _userManager.AddToRoleAsync(user, Roles.ServerAdmin);

                        if (_Options.DisableRegistration)
                        {
                            // Once the admin user has been created lock subsequent user registrations (needs to be disabled for unit tests that require multiple users).
                            policies.LockSubscription = true;
                            await _SettingsRepository.UpdateSetting(policies);
                        }
                    }

                    var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);

                    var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
                    RegisteredUserId = user.Id;

                    _EmailSenderFactory.GetEmailSender().SendEmailConfirmation(model.Email, callbackUrl);
                    if (!policies.RequiresConfirmedEmail)
                    {
                        if (logon)
                        {
                            await _signInManager.SignInAsync(user, isPersistent : false);
                        }
                        return(RedirectToLocal(returnUrl));
                    }
                    else
                    {
                        TempData["StatusMessage"] = "Account created, please confirm your email";
                        return(View());
                    }
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return(View(model));
        }
        async Task Notify(InvoiceEntity invoice, InvoiceEvent invoiceEvent, bool extendedNotification, bool sendMail)
        {
            var dto          = invoice.EntityToDTO();
            var notification = new InvoicePaymentNotificationEventWrapper()
            {
                Data = new InvoicePaymentNotification()
                {
                    Id              = dto.Id,
                    Currency        = dto.Currency,
                    CurrentTime     = dto.CurrentTime,
                    ExceptionStatus = dto.ExceptionStatus,
                    ExpirationTime  = dto.ExpirationTime,
                    InvoiceTime     = dto.InvoiceTime,
                    PosData         = dto.PosData,
                    Price           = dto.Price,
                    Status          = dto.Status,
                    BuyerFields     = invoice.RefundMail == null ? null : new Newtonsoft.Json.Linq.JObject()
                    {
                        new JProperty("buyerEmail", invoice.RefundMail)
                    },
                    PaymentSubtotals = dto.PaymentSubtotals,
                    PaymentTotals    = dto.PaymentTotals,
                    AmountPaid       = dto.AmountPaid,
                    ExchangeRates    = dto.ExchangeRates,
                    OrderId          = dto.OrderId
                },
                Event = new InvoicePaymentNotificationEvent()
                {
                    Code = (int)invoiceEvent.EventCode,
                    Name = invoiceEvent.Name
                },
                ExtendedNotification = extendedNotification,
                NotificationURL      = invoice.NotificationURL?.AbsoluteUri
            };

            // For lightning network payments, paid, confirmed and completed come all at once.
            // So despite the event is "paid" or "confirmed" the Status of the invoice is technically complete
            // This confuse loggers who think their endpoint get duplicated events
            // So here, we just override the status expressed by the notification
            if (invoiceEvent.Name == InvoiceEvent.Confirmed)
            {
                notification.Data.Status = InvoiceState.ToString(InvoiceStatusLegacy.Confirmed);
            }
            if (invoiceEvent.Name == InvoiceEvent.PaidInFull)
            {
                notification.Data.Status = InvoiceState.ToString(InvoiceStatusLegacy.Paid);
            }
            //////////////////

            // We keep backward compatibility with bitpay by passing BTC info to the notification
            // we don't pass other info, as it is a bad idea to use IPN data for logic processing (can be faked)
            var btcCryptoInfo = dto.CryptoInfo.FirstOrDefault(c => c.GetpaymentMethodId() == new PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike) && !string.IsNullOrEmpty(c.Address));

            if (btcCryptoInfo != null)
            {
#pragma warning disable CS0618
                notification.Data.Rate     = dto.Rate;
                notification.Data.Url      = dto.Url;
                notification.Data.BTCDue   = dto.BTCDue;
                notification.Data.BTCPaid  = dto.BTCPaid;
                notification.Data.BTCPrice = dto.BTCPrice;
#pragma warning restore CS0618
            }

            if (sendMail && !String.IsNullOrEmpty(invoice.NotificationEmail))
            {
                var json  = NBitcoin.JsonConverters.Serializer.ToString(notification);
                var store = await _StoreRepository.FindStore(invoice.StoreId);

                var storeName = store.StoreName ?? "BTCPay Server";
                var emailBody = $"Store: {storeName}<br>" +
                                $"Invoice ID: {notification.Data.Id}<br>" +
                                $"Status: {notification.Data.Status}<br>" +
                                $"Amount: {notification.Data.Price} {notification.Data.Currency}<br>" +
                                $"<br><details><summary>Details</summary><pre>{json}</pre></details>";

                (await _EmailSenderFactory.GetEmailSender(invoice.StoreId)).SendEmail(
                    invoice.NotificationEmail,
                    $"{storeName} Invoice Notification - ${invoice.StoreId}",
                    emailBody);
            }

            if (invoice.NotificationURL != null)
            {
                _Queue.Enqueue(invoice.Id, (cancellationToken) => NotifyHttp(new ScheduledJob()
                {
                    TryCount = 0, Notification = notification
                }, cancellationToken));
            }
        }
Beispiel #13
0
        void Notify(InvoiceEntity invoice, InvoiceEvent invoiceEvent, bool extendedNotification)
        {
            var dto          = invoice.EntityToDTO(_NetworkProvider);
            var notification = new InvoicePaymentNotificationEventWrapper()
            {
                Data = new InvoicePaymentNotification()
                {
                    Id              = dto.Id,
                    Currency        = dto.Currency,
                    CurrentTime     = dto.CurrentTime,
                    ExceptionStatus = dto.ExceptionStatus,
                    ExpirationTime  = dto.ExpirationTime,
                    InvoiceTime     = dto.InvoiceTime,
                    PosData         = dto.PosData,
                    Price           = dto.Price,
                    Status          = dto.Status,
                    BuyerFields     = invoice.RefundMail == null ? null : new Newtonsoft.Json.Linq.JObject()
                    {
                        new JProperty("buyerEmail", invoice.RefundMail)
                    },
                    PaymentSubtotals = dto.PaymentSubtotals,
                    PaymentTotals    = dto.PaymentTotals,
                    AmountPaid       = dto.AmountPaid,
                    ExchangeRates    = dto.ExchangeRates,
                },
                Event = new InvoicePaymentNotificationEvent()
                {
                    Code = invoiceEvent.EventCode,
                    Name = invoiceEvent.Name
                },
                ExtendedNotification = extendedNotification,
                NotificationURL      = invoice.NotificationURL
            };

            // For lightning network payments, paid, confirmed and completed come all at once.
            // So despite the event is "paid" or "confirmed" the Status of the invoice is technically complete
            // This confuse loggers who think their endpoint get duplicated events
            // So here, we just override the status expressed by the notification
            if (invoiceEvent.Name == InvoiceEvent.Confirmed)
            {
                notification.Data.Status = InvoiceState.ToString(InvoiceStatus.Confirmed);
            }
            if (invoiceEvent.Name == InvoiceEvent.PaidInFull)
            {
                notification.Data.Status = InvoiceState.ToString(InvoiceStatus.Paid);
            }
            //////////////////

            // We keep backward compatibility with bitpay by passing BTC info to the notification
            // we don't pass other info, as it is a bad idea to use IPN data for logic processing (can be faked)
            var btcCryptoInfo = dto.CryptoInfo.FirstOrDefault(c => c.GetpaymentMethodId() == new PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike));

            if (btcCryptoInfo != null)
            {
#pragma warning disable CS0618
                notification.Data.Rate     = dto.Rate;
                notification.Data.Url      = dto.Url;
                notification.Data.BTCDue   = dto.BTCDue;
                notification.Data.BTCPaid  = dto.BTCPaid;
                notification.Data.BTCPrice = dto.BTCPrice;
#pragma warning restore CS0618
            }

            CancellationTokenSource cts = new CancellationTokenSource(10000);

            if (!String.IsNullOrEmpty(invoice.NotificationEmail))
            {
                var emailBody = NBitcoin.JsonConverters.Serializer.ToString(notification);

                _EmailSenderFactory.GetEmailSender(invoice.StoreId).SendEmail(
                    invoice.NotificationEmail,
                    $"BtcPayServer Invoice Notification - ${invoice.StoreId}",
                    emailBody);
            }
            if (string.IsNullOrEmpty(invoice.NotificationURL) || !Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute))
            {
                return;
            }
            var invoiceStr = NBitcoin.JsonConverters.Serializer.ToString(new ScheduledJob()
            {
                TryCount = 0, Notification = notification
            });
            if (!string.IsNullOrEmpty(invoice.NotificationURL))
            {
                _JobClient.Schedule(() => NotifyHttp(invoiceStr), TimeSpan.Zero);
            }
        }
Beispiel #14
0
 private async Task <bool> IsEmailConfigured(string storeId)
 {
     return((await(_emailSenderFactory.GetEmailSender(storeId) as EmailSender)?.GetEmailSettings())?.IsComplete() is true);
 }