diff --git a/VirtoCommerce.CoreModule.Data/Notifications/EmailConfirmationNotification.cs b/VirtoCommerce.CoreModule.Data/Notifications/EmailConfirmationNotification.cs
new file mode 100644
index 00000000..d2ddd812
--- /dev/null
+++ b/VirtoCommerce.CoreModule.Data/Notifications/EmailConfirmationNotification.cs
@@ -0,0 +1,15 @@
+using VirtoCommerce.Platform.Core.Notifications;
+
+namespace VirtoCommerce.CoreModule.Data.Notifications
+{
+ public class EmailConfirmationNotification : EmailNotification
+ {
+ public EmailConfirmationNotification(IEmailNotificationSendingGateway gateway)
+ : base(gateway)
+ {
+ }
+
+ [NotificationParameter("E-mail confirmation URL")]
+ public string Url { get; set; }
+ }
+}
diff --git a/VirtoCommerce.CoreModule.Data/VirtoCommerce.CoreModule.Data.csproj b/VirtoCommerce.CoreModule.Data/VirtoCommerce.CoreModule.Data.csproj
index 6719dece..ede5d483 100644
--- a/VirtoCommerce.CoreModule.Data/VirtoCommerce.CoreModule.Data.csproj
+++ b/VirtoCommerce.CoreModule.Data/VirtoCommerce.CoreModule.Data.csproj
@@ -133,6 +133,7 @@
+
diff --git a/VirtoCommerce.CoreModule.Web/Controllers/Api/StoreFrontSecurityController.cs b/VirtoCommerce.CoreModule.Web/Controllers/Api/StoreFrontSecurityController.cs
index befaea8d..f7bdeb2a 100644
--- a/VirtoCommerce.CoreModule.Web/Controllers/Api/StoreFrontSecurityController.cs
+++ b/VirtoCommerce.CoreModule.Web/Controllers/Api/StoreFrontSecurityController.cs
@@ -5,6 +5,7 @@
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;
+using VirtoCommerce.CoreModule.Data.Notifications;
using VirtoCommerce.CoreModule.Web.Converters;
using VirtoCommerce.CoreModule.Web.Model;
using VirtoCommerce.Domain.Customer.Services;
@@ -21,14 +22,22 @@ public class StorefrontSecurityController : ApiController
{
private readonly ISecurityService _securityService;
private readonly Func _signInManagerFactory;
+ private readonly Func _userManagerFactory;
private readonly INotificationManager _notificationManager;
private readonly IStoreService _storeService;
private readonly IMemberService _memberService;
- public StorefrontSecurityController(ISecurityService securityService, Func signInManagerFactory, INotificationManager notificationManager, IStoreService storeService, IMemberService memberService)
+ public StorefrontSecurityController(
+ ISecurityService securityService,
+ Func signInManagerFactory,
+ Func userManagerFactory,
+ INotificationManager notificationManager,
+ IStoreService storeService,
+ IMemberService memberService)
{
_securityService = securityService;
_signInManagerFactory = signInManagerFactory;
+ _userManagerFactory = userManagerFactory;
_notificationManager = notificationManager;
_storeService = storeService;
_memberService = memberService;
@@ -233,7 +242,7 @@ public async Task GenerateResetPasswordToken(string userId, s
notification.Sender = store.Email;
notification.IsActive = true;
- var member = _memberService.GetByIds(new [] { userId }).FirstOrDefault();
+ var member = _memberService.GetByIds(new[] { userId }).FirstOrDefault();
if (member != null)
{
var email = member.Emails.FirstOrDefault();
@@ -270,6 +279,57 @@ public async Task ResetPassword(string userId, string token,
return Ok(result);
}
+ [HttpPost]
+ [Route("user/email/sendconfirmation")]
+ [ResponseType(typeof(void))]
+ public async Task SendEmailConfirmation(string userId, string storeName, string language, string callbackUrl)
+ {
+ using (var userManager = _userManagerFactory())
+ {
+ var member = _memberService.GetByIds(new[] { userId }).FirstOrDefault();
+ if (member != null)
+ {
+ var store = _storeService.GetById(storeName);
+
+ var uriBuilder = new UriBuilder(callbackUrl);
+ var query = HttpUtility.ParseQueryString(uriBuilder.Query);
+ var token = await userManager.GenerateEmailConfirmationTokenAsync(userId);
+ query["code"] = token;
+ uriBuilder.Query = query.ToString();
+
+ var notification = _notificationManager.GetNewNotification(storeName, "Store", language);
+ var email = member.Emails.FirstOrDefault();
+ if (!string.IsNullOrEmpty(email))
+ {
+ notification.Recipient = email;
+ }
+ notification.Url = uriBuilder.ToString();
+ notification.Sender = store.Email;
+ notification.IsActive = true;
+ _notificationManager.ScheduleSendNotification(notification);
+ }
+ }
+
+ return StatusCode(HttpStatusCode.NoContent);
+ }
+
+ [HttpPost]
+ [Route("user/email/confirm")]
+ [ResponseType(typeof(SecurityResult))]
+ public async Task ConfirmEmail(string userId, string token)
+ {
+ if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(token))
+ {
+ return BadRequest();
+ }
+
+ using (var userManager = _userManagerFactory())
+ {
+ var result = await userManager.ConfirmEmailAsync(userId, token);
+
+ return Ok(result);
+ }
+ }
}
}
diff --git a/VirtoCommerce.CoreModule.Web/Module.cs b/VirtoCommerce.CoreModule.Web/Module.cs
index c19c0a27..8cb34eed 100644
--- a/VirtoCommerce.CoreModule.Web/Module.cs
+++ b/VirtoCommerce.CoreModule.Web/Module.cs
@@ -4,6 +4,7 @@
using Hangfire;
using Microsoft.Practices.Unity;
using VirtoCommerce.CoreModule.Data.Indexing;
+using VirtoCommerce.CoreModule.Data.Notifications;
using VirtoCommerce.CoreModule.Data.Observers;
using VirtoCommerce.CoreModule.Data.Payment;
using VirtoCommerce.CoreModule.Data.Repositories;
@@ -14,6 +15,7 @@
using VirtoCommerce.CoreModule.Web.BackgroundJobs;
using VirtoCommerce.CoreModule.Web.ExportImport;
using VirtoCommerce.CoreModule.Web.JsonConverters;
+using VirtoCommerce.CoreModule.Web.Resources;
using VirtoCommerce.Domain.Commerce.Model;
using VirtoCommerce.Domain.Commerce.Services;
using VirtoCommerce.Domain.Customer.Events;
@@ -24,6 +26,7 @@
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Platform.Core.ExportImport;
using VirtoCommerce.Platform.Core.Modularity;
+using VirtoCommerce.Platform.Core.Notifications;
using VirtoCommerce.Platform.Core.Settings;
using VirtoCommerce.Platform.Data.Infrastructure;
using VirtoCommerce.Platform.Data.Infrastructure.Interceptors;
@@ -129,6 +132,20 @@ public override void PostInitialize()
var taxService = _container.Resolve();
var paymentService = _container.Resolve();
var moduleSettings = settingsManager.GetModuleSettings("VirtoCommerce.Core");
+ var notificationManager = _container.Resolve();
+ var emailGateway = _container.Resolve();
+
+ notificationManager.RegisterNotificationType(() => new EmailConfirmationNotification(emailGateway)
+ {
+ DisplayName = "Email confirmation notification",
+ Description = "This e-mail notification is for confirmation a new registered user e-mail",
+ NotificationTemplate = new NotificationTemplate
+ {
+ Language = "en-US",
+ Subject = EmailConfirmationResource.Subject,
+ Body = EmailConfirmationResource.Body
+ }
+ });
taxService.RegisterTaxProvider(() => new FixedTaxRateProvider(moduleSettings.First(x => x.Name == "VirtoCommerce.Core.FixedTaxRateProvider.Rate"))
{
diff --git a/VirtoCommerce.CoreModule.Web/Resources/EmailConfirmationResource.Designer.cs b/VirtoCommerce.CoreModule.Web/Resources/EmailConfirmationResource.Designer.cs
new file mode 100644
index 00000000..8e5f165d
--- /dev/null
+++ b/VirtoCommerce.CoreModule.Web/Resources/EmailConfirmationResource.Designer.cs
@@ -0,0 +1,81 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace VirtoCommerce.CoreModule.Web.Resources {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class EmailConfirmationResource {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal EmailConfirmationResource() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("VirtoCommerce.CoreModule.Web.Resources.EmailConfirmationResource", typeof(EmailConfirmationResource).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to To complete your create account process please click this link: <a href="{{ url }}">{{ url }}</a>.
+ ///
+ internal static string Body {
+ get {
+ return ResourceManager.GetString("Body", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Email confirmation.
+ ///
+ internal static string Subject {
+ get {
+ return ResourceManager.GetString("Subject", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/VirtoCommerce.CoreModule.Web/Resources/EmailConfirmationResource.resx b/VirtoCommerce.CoreModule.Web/Resources/EmailConfirmationResource.resx
new file mode 100644
index 00000000..697f36e9
--- /dev/null
+++ b/VirtoCommerce.CoreModule.Web/Resources/EmailConfirmationResource.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ To complete your create account process please click this link: <a href="{{ url }}">{{ url }}</a>
+
+
+ Email confirmation
+
+
\ No newline at end of file
diff --git a/VirtoCommerce.CoreModule.Web/VirtoCommerce.CoreModule.Web.csproj b/VirtoCommerce.CoreModule.Web/VirtoCommerce.CoreModule.Web.csproj
index 0a74caac..342cbaf0 100644
--- a/VirtoCommerce.CoreModule.Web/VirtoCommerce.CoreModule.Web.csproj
+++ b/VirtoCommerce.CoreModule.Web/VirtoCommerce.CoreModule.Web.csproj
@@ -175,6 +175,11 @@
+
+ True
+ True
+ EmailConfirmationResource.resx
+
@@ -275,6 +280,12 @@
+
+
+ ResXFileCodeGenerator
+ EmailConfirmationResource.Designer.cs
+
+
10.0
$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
diff --git a/VirtoCommerce.CoreModule.sln b/VirtoCommerce.CoreModule.sln
index 1656097d..a2f65267 100644
--- a/VirtoCommerce.CoreModule.sln
+++ b/VirtoCommerce.CoreModule.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26730.10
+VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VirtoCommerce.CoreModule.Web", "VirtoCommerce.CoreModule.Web\VirtoCommerce.CoreModule.Web.csproj", "{47D7C89C-62A8-44EC-B544-F24E874192AC}"
EndProject
@@ -18,8 +18,8 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {47D7C89C-62A8-44EC-B544-F24E874192AC}.Debug|Any CPU.ActiveCfg = Release|Any CPU
- {47D7C89C-62A8-44EC-B544-F24E874192AC}.Debug|Any CPU.Build.0 = Release|Any CPU
+ {47D7C89C-62A8-44EC-B544-F24E874192AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {47D7C89C-62A8-44EC-B544-F24E874192AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47D7C89C-62A8-44EC-B544-F24E874192AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47D7C89C-62A8-44EC-B544-F24E874192AC}.Release|Any CPU.Build.0 = Release|Any CPU
{3A627001-02C6-4809-AB42-D517C636E7B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU