diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Authorization/ProfileAuthorizationHandler.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Authorization/ProfileAuthorizationHandler.cs index c145b313..a4331017 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Authorization/ProfileAuthorizationHandler.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Authorization/ProfileAuthorizationHandler.cs @@ -167,10 +167,17 @@ protected override async Task HandleRequirementAsync(AuthorizationHandlerContext updatePersonalDataCommand.UserId = currentUserId; result = true; } - else if (context.Resource is InviteUserCommand inviteUserCommand && currentContact != null) + else if (context.Resource is InviteUserCommand inviteUserCommand) { - var currentUser = await userManager.FindByIdAsync(currentUserId); - result = currentContact.Organizations.Contains(inviteUserCommand.OrganizationId) && currentUser.StoreId.EqualsInvariant(inviteUserCommand.StoreId); + if (!string.IsNullOrEmpty(inviteUserCommand.OrganizationId) && currentContact != null) + { + var currentUser = await userManager.FindByIdAsync(currentUserId); + result = currentContact.Organizations.Contains(inviteUserCommand.OrganizationId) && currentUser.StoreId.EqualsInvariant(inviteUserCommand.StoreId); + } + else + { + result = true; + } } else if (context.Resource is LockOrganizationContactCommand lockOrganizationContact) { diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/InviteUserCommand.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/InviteUserCommand.cs index c78b13d6..62daaa96 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/InviteUserCommand.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/InviteUserCommand.cs @@ -16,5 +16,7 @@ public class InviteUserCommand : ICommand public string Message { get; set; } public string[] RoleIds { get; set; } + + public string CustomerOrderId { get; set; } } } diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/InviteUserCommandHandler.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/InviteUserCommandHandler.cs index 3483db74..7633f0ef 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/InviteUserCommandHandler.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/InviteUserCommandHandler.cs @@ -66,9 +66,14 @@ public virtual async Task Handle(InviteUserCommand reque FirstName = string.Empty, LastName = string.Empty, FullName = string.Empty, - Organizations = new List { request.OrganizationId }, Emails = new List { email } }; + + if (!string.IsNullOrEmpty(request.OrganizationId)) + { + contact.Organizations = new List { request.OrganizationId }; + } + await _memberService.SaveChangesAsync(new Member[] { contact }); var user = new ApplicationUser { UserName = email, Email = email, MemberId = contact.Id, StoreId = request.StoreId }; @@ -153,8 +158,18 @@ protected virtual async Task SendNotificationAsync(InviteUserCommand request, St var user = await userManager.FindByEmailAsync(email); var token = await userManager.GeneratePasswordResetTokenAsync(user); - var notification = await _notificationSearchService.GetNotificationAsync(new TenantIdentity(store.Id, nameof(Store))); + // take notification + RegistrationInvitationNotificationBase notification = !string.IsNullOrEmpty(request.OrganizationId) + ? await _notificationSearchService.GetNotificationAsync(new TenantIdentity(store.Id, nameof(Store))) + : await _notificationSearchService.GetNotificationAsync(new TenantIdentity(store.Id, nameof(Store))); + notification.InviteUrl = $"{store.Url.TrimLastSlash()}{request.UrlSuffix.NormalizeUrlSuffix()}?userId={user.Id}&email={HttpUtility.UrlEncode(user.Email)}&token={Uri.EscapeDataString(token)}"; + + if (!string.IsNullOrEmpty(request.CustomerOrderId)) + { + notification.InviteUrl = $"{notification.InviteUrl}&customerOrderId={request.CustomerOrderId}"; + } + notification.Message = request.Message; notification.To = user.Email; notification.From = store.Email; diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterByInvitationCommand.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterByInvitationCommand.cs index eb75ccc8..d5d6abae 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterByInvitationCommand.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterByInvitationCommand.cs @@ -18,5 +18,7 @@ public class RegisterByInvitationCommand : ICommand public string Username { get; set; } public string Password { get; set; } + + public string CustomerOrderId { get; set; } } } diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterByInvitationCommandHandler.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterByInvitationCommandHandler.cs index 5b29ed96..14e3ad8a 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterByInvitationCommandHandler.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterByInvitationCommandHandler.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Hosting; using VirtoCommerce.CustomerModule.Core.Model; using VirtoCommerce.CustomerModule.Core.Services; +using VirtoCommerce.ExperienceApiModule.XOrder.Commands; using VirtoCommerce.Platform.Core.Common; using VirtoCommerce.Platform.Core.Security; using VirtoCommerce.ProfileExperienceApiModule.Data.Extensions; @@ -88,7 +89,13 @@ public virtual async Task Handle(RegisterByInvitationCom await _memberService.SaveChangesAsync(new Member[] { contact }); - await SendRegistrationNotification(user, contact, cancellationToken); + // associate order + if (!string.IsNullOrEmpty(request.CustomerOrderId)) + { + await TransferOrderAsync(request.CustomerOrderId, user.Id, contact.FullName, cancellationToken); + } + + await SendRegistrationNotificationAsync(user, contact, cancellationToken); } return SetResponse(identityResult); @@ -100,7 +107,7 @@ public virtual async Task Handle(RegisterByInvitationCom Succeeded = identityResult.Succeeded, }; - private async Task SendRegistrationNotification(ApplicationUser user, Contact contact, CancellationToken cancellationToken) + private async Task SendRegistrationNotificationAsync(ApplicationUser user, Contact contact, CancellationToken cancellationToken) { var store = await _storeService.GetByIdAsync(user.StoreId); if (store == null) @@ -119,5 +126,17 @@ private async Task SendRegistrationNotification(ApplicationUser user, Contact co await _mediator.Send(registrationNotificationRequest, cancellationTokenSource.Token); } + private async Task TransferOrderAsync(string customerOrderId, string userId, string userName, CancellationToken cancellationToken) + { + var transferOrderCommand = new TransferOrderCommand + { + CustomerOrderId = customerOrderId, + ToUserId = userId, + UserName = userName, + }; + + var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + await _mediator.Send(transferOrderCommand, cancellationTokenSource.Token); + } } } diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterRequestCommandHandler.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterRequestCommandHandler.cs index 458e4dae..6c64dc64 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterRequestCommandHandler.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/RegisterRequestCommandHandler.cs @@ -124,11 +124,9 @@ protected virtual async Task BeforeProcessRequestAsync(RegisterRequestCommand re EmailVerificationFlow = CurrentStore.GetEmailVerificationFlow(); // Read Settings - DefaultContactStatus = CurrentStore.Settings - .GetSettingValue(CustomerSettings.ContactDefaultStatus.Name, null); + DefaultContactStatus = CurrentStore.Settings.GetValue(CustomerSettings.ContactDefaultStatus); - DefaultOrganizationStatus = CurrentStore.Settings - .GetSettingValue(CustomerSettings.OrganizationDefaultStatus.Name, null); + DefaultOrganizationStatus = CurrentStore.Settings.GetValue(CustomerSettings.OrganizationDefaultStatus); MaintainerRole = await GetMaintainerRole(result, tokenSource); } diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/SendVerifyEmailCommandHandler.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/SendVerifyEmailCommandHandler.cs index bab7701e..e950fe30 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/SendVerifyEmailCommandHandler.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Commands/SendVerifyEmailCommandHandler.cs @@ -62,7 +62,7 @@ public virtual async Task Handle(SendVerifyEmailCommand request, Cancellat return true; } - if (store.Settings.GetSettingValue(StoreSettings.EmailVerificationEnabled.Name, (bool)StoreSettings.EmailVerificationEnabled.DefaultValue)) + if (store.Settings.GetValue(StoreSettings.EmailVerificationEnabled)) { await SendConfirmationEmailNotificationAsync(store, user, request.LanguageCode); } diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Extensions/StoreExtensions.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Extensions/StoreExtensions.cs index 5c1c2ec0..c5738b5b 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Extensions/StoreExtensions.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Extensions/StoreExtensions.cs @@ -8,8 +8,8 @@ public static class StoreExtensions { public static string GetEmailVerificationFlow(this Store store) { - var emailVerificationEnabled = store.Settings.GetSettingValue(StoreSettings.EmailVerificationEnabled.Name, (bool)StoreSettings.EmailVerificationEnabled.DefaultValue); - var emailVerificationRequired = store.Settings.GetSettingValue(StoreSettings.EmailVerificationRequired.Name, (bool)StoreSettings.EmailVerificationRequired.DefaultValue); + var emailVerificationEnabled = store.Settings.GetValue(StoreSettings.EmailVerificationEnabled); + var emailVerificationRequired = store.Settings.GetValue(StoreSettings.EmailVerificationRequired); if (!emailVerificationEnabled) { diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/InputInviteUserType.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/InputInviteUserType.cs index 5f0b7257..69613021 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/InputInviteUserType.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/InputInviteUserType.cs @@ -8,11 +8,12 @@ public class InputInviteUserType : InputObjectGraphType public InputInviteUserType() { Field>(nameof(InviteUserCommand.StoreId), "ID of store which will send invites"); - Field>(nameof(InviteUserCommand.OrganizationId), "ID of organization where contact will be added for user"); + Field(nameof(InviteUserCommand.OrganizationId), "ID of organization where contact will be added for user"); Field(nameof(InviteUserCommand.UrlSuffix), "Optional URL suffix: you may provide here relative URL to your page which handle registration by invite"); Field>>>(nameof(InviteUserCommand.Emails), "Emails which will receive invites"); Field(nameof(InviteUserCommand.Message), "Optional message to include into email with instructions which invites persons will see"); Field>>(nameof(InviteUserCommand.RoleIds), "Role IDs or names to be assigned to the invited user"); + Field(nameof(InviteUserCommand.CustomerOrderId), "Customer order Id to be associated with this user."); } } } diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/InputRegisterByInvitationType.cs b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/InputRegisterByInvitationType.cs index c1555fd9..9ff72106 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/InputRegisterByInvitationType.cs +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/Schemas/InputRegisterByInvitationType.cs @@ -14,6 +14,7 @@ public InputRegisterByInvitationType() Field(nameof(RegisterByInvitationCommand.Phone), "Phone"); Field>(nameof(RegisterByInvitationCommand.Username), "Username"); Field>(nameof(RegisterByInvitationCommand.Password), "Password"); + Field(nameof(RegisterByInvitationCommand.CustomerOrderId), "Customer order Id to be associated with this user."); } } } diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj b/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj index f9a3a198..8adf0ec0 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Data/VirtoCommerce.ProfileExperienceApiModule.Data.csproj @@ -21,10 +21,11 @@ - + + - - + + diff --git a/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest b/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest index 0ff9b525..f679a033 100644 --- a/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest +++ b/src/VirtoCommerce.ProfileExperienceApiModule.Web/module.manifest @@ -3,13 +3,13 @@ VirtoCommerce.ProfileExperienceApiModule 3.410.0 - 3.400.0 + 3.413.0 - + - +