From 928c7ca8a3acb5931f8b3f5b860e294770a2048e Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 23 Dec 2021 11:01:00 +0300 Subject: [PATCH 1/9] Moved and renamed CookieConstants --- .../src/EShopOnAbp.PublicWeb/CookieConstants.cs | 8 -------- .../EShopConstants.cs | 7 +++++++ 2 files changed, 7 insertions(+), 8 deletions(-) delete mode 100644 apps/public-web/src/EShopOnAbp.PublicWeb/CookieConstants.cs create mode 100644 shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/CookieConstants.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/CookieConstants.cs deleted file mode 100644 index 1994218b..00000000 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/CookieConstants.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace EShopOnAbp.PublicWeb; - -public static class CookieConstants -{ - public const string AnonymousUserCookieName = "eshop_anonymousId"; -} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs b/shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs new file mode 100644 index 00000000..87a36a2f --- /dev/null +++ b/shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs @@ -0,0 +1,7 @@ +namespace EShopOnAbp.Shared.Hosting.AspNetCore; + +public static class EShopConstants +{ + public const string AnonymousUserCookieName = "eshop_anonymousId"; + public const string AnonymousUserClaimName = "anonymous_id"; +} \ No newline at end of file From 8075da5af4158a34f29da333983cb0c096491b3f Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 23 Dec 2021 11:01:46 +0300 Subject: [PATCH 2/9] added new claim --- .../EShopOnAbpAuthServerModule.cs | 8 +++ .../EShopUserClaimsPrincipalFactory.cs | 56 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs index 5110d159..bcaf4c74 100644 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs @@ -99,6 +99,14 @@ namespace EShopOnAbp.AuthServer options.IsEnabled = true; }); + + Configure(options => + { + options.RequestedClaims.AddRange(new[]{ + EShopConstants.AnonymousUserClaimName + }); + }); + Configure(options => { options.ApplicationName = "AuthServer"; diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs new file mode 100644 index 00000000..db519d7c --- /dev/null +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs @@ -0,0 +1,56 @@ +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using EShopOnAbp.Shared.Hosting.AspNetCore; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; +using Volo.Abp.Security.Claims; +using IdentityRole = Volo.Abp.Identity.IdentityRole; +using IdentityUser = Volo.Abp.Identity.IdentityUser; + +namespace EShopOnAbp.AuthServer; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(AbpUserClaimsPrincipalFactory))] +public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory +{ + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ILogger _logger; + protected HttpContext HttpContext => _httpContextAccessor.HttpContext; + + public EShopUserClaimsPrincipalFactory( + UserManager userManager, + RoleManager roleManager, + IOptions options, + ICurrentPrincipalAccessor currentPrincipalAccessor, + IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory, + IHttpContextAccessor httpContextAccessor, ILogger logger) : base(userManager, + roleManager, + options, + currentPrincipalAccessor, + abpClaimsPrincipalFactory) + { + _httpContextAccessor = httpContextAccessor; + _logger = logger; + } + + public override async Task CreateAsync(IdentityUser user) + { + var principal = await base.CreateAsync(user); + if (HttpContext.Request.Cookies.ContainsKey(EShopConstants.AnonymousUserCookieName)) + { + HttpContext.Request.Cookies.TryGetValue(EShopConstants.AnonymousUserCookieName, out var anonymousUserId); + + principal.Identities.First() + .AddClaim(new Claim(EShopConstants.AnonymousUserClaimName, anonymousUserId)); + _logger.LogInformation( + $"Added {EShopConstants.AnonymousUserClaimName} claim of AnonymousUserId from cookies:{anonymousUserId}"); + } + + return principal; + } +} \ No newline at end of file From 9b6eb03b792f264a661c00997c91dcde7262c865 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 23 Dec 2021 13:46:55 +0300 Subject: [PATCH 3/9] updated basket --- .../wwwroot/client-proxies/basket-proxy.js | 7 ++++ .../IBasketAppService.cs | 1 + .../BasketAppService.cs | 41 +++++++++++++++++-- .../BasketClientProxy.Generated.cs | 5 +++ .../ClientProxies/basket-generate-proxy.json | 15 +++++++ 5 files changed, 65 insertions(+), 4 deletions(-) diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/client-proxies/basket-proxy.js b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/client-proxies/basket-proxy.js index de10ce04..eedba967 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/client-proxies/basket-proxy.js +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/client-proxies/basket-proxy.js @@ -25,6 +25,13 @@ }, ajaxParams)); }; + eShopOnAbp.basketService.basket.mergeBaskets = function(ajaxParams) { + return abp.ajax($.extend(true, { + url: abp.appPath + 'api/basket/basket/merge-baskets', + type: 'POST' + }, ajaxParams)); + }; + eShopOnAbp.basketService.basket.addProduct = function(input, ajaxParams) { return abp.ajax($.extend(true, { url: abp.appPath + 'api/basket/basket/product', diff --git a/services/basket/src/EShopOnAbp.BasketService.Application.Contracts/IBasketAppService.cs b/services/basket/src/EShopOnAbp.BasketService.Application.Contracts/IBasketAppService.cs index 55a4ba0a..2bf27fe7 100644 --- a/services/basket/src/EShopOnAbp.BasketService.Application.Contracts/IBasketAppService.cs +++ b/services/basket/src/EShopOnAbp.BasketService.Application.Contracts/IBasketAppService.cs @@ -8,6 +8,7 @@ public interface IBasketAppService : IApplicationService { Task GetAsync(); Task GetByAnonymousUserIdAsync(Guid id); + Task MergeBasketsAsync(); Task AddProductAsync(AddProductDto input); Task RemoveProductAsync(RemoveProductDto input); Task PurchaseAsync(); diff --git a/services/basket/src/EShopOnAbp.BasketService.Application/BasketAppService.cs b/services/basket/src/EShopOnAbp.BasketService.Application/BasketAppService.cs index 2aab9990..6ae2f72b 100644 --- a/services/basket/src/EShopOnAbp.BasketService.Application/BasketAppService.cs +++ b/services/basket/src/EShopOnAbp.BasketService.Application/BasketAppService.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Users; using EShopOnAbp.CatalogService.Products; +using Microsoft.Extensions.Logging; using Volo.Abp; using Volo.Abp.EventBus.Distributed; @@ -15,7 +16,6 @@ public class BasketAppService : BasketServiceAppService, IBasketAppService private readonly IBasketRepository _basketRepository; private readonly IBasketProductService _basketProductService; private readonly IDistributedEventBus _distributedEventBus; - private Guid _anonymousUserId { get; set; } public BasketAppService( IBasketRepository basketRepository, @@ -36,14 +36,47 @@ public class BasketAppService : BasketServiceAppService, IBasketAppService public async Task GetByAnonymousUserIdAsync(Guid id) { var basket = await _basketRepository.GetAsync(id); - _anonymousUserId = id; + ; return await GetBasketDtoAsync(basket); } - public async Task AddProductAsync(AddProductDto input) + public async Task MergeBasketsAsync() { - Console.WriteLine("========================= AnonymousId: "+input.AnonymousId); + //TODO: move to custom shared project + var anonymousUserIdString = CurrentUser.FindClaimValue("anonymous_id"); + + foreach (var claim in CurrentUser.GetAllClaims()) + { + Logger.LogInformation($"claim type:{ claim.Type} - value:{claim.Value}"); + } + if (!Guid.TryParse(anonymousUserIdString, out Guid anonymousUserId)) + { + Logger.LogError($"Couldn't parse anonymous Id from claim!{anonymousUserIdString}"); + } + + Basket anonymousUserBasket = await _basketRepository.GetAsync(anonymousUserId); + if (!CurrentUser.IsAuthenticated) + { + Logger.LogWarning($"User is not authenticated! Merging baskets failed!"); + return await GetBasketDtoAsync(anonymousUserBasket); + } + + var userBasket = await _basketRepository.GetAsync(CurrentUser.GetId()); + foreach (var item in anonymousUserBasket.Items) + { + userBasket.AddProduct(item.ProductId, item.Count); + } + + await _basketRepository.UpdateAsync(userBasket); + anonymousUserBasket.Clear(); + await _basketRepository.UpdateAsync(anonymousUserBasket); + + return await GetBasketDtoAsync(userBasket); + } + + public async Task AddProductAsync(AddProductDto input) + { Guid userId = CurrentUser.IsAuthenticated ? CurrentUser.GetId() : input.AnonymousId.GetValueOrDefault(); var basket = await _basketRepository.GetAsync(userId); diff --git a/services/basket/src/EShopOnAbp.BasketService.HttpApi.Client/ClientProxies/BasketClientProxy.Generated.cs b/services/basket/src/EShopOnAbp.BasketService.HttpApi.Client/ClientProxies/BasketClientProxy.Generated.cs index 6a723592..b8174b87 100644 --- a/services/basket/src/EShopOnAbp.BasketService.HttpApi.Client/ClientProxies/BasketClientProxy.Generated.cs +++ b/services/basket/src/EShopOnAbp.BasketService.HttpApi.Client/ClientProxies/BasketClientProxy.Generated.cs @@ -28,6 +28,11 @@ namespace EShopOnAbp.BasketService.ClientProxies }); } + public virtual async Task MergeBasketsAsync() + { + return await RequestAsync(nameof(MergeBasketsAsync)); + } + public virtual async Task AddProductAsync(AddProductDto input) { return await RequestAsync(nameof(AddProductAsync), new ClientProxyRequestTypeValue diff --git a/services/basket/src/EShopOnAbp.BasketService.HttpApi.Client/ClientProxies/basket-generate-proxy.json b/services/basket/src/EShopOnAbp.BasketService.HttpApi.Client/ClientProxies/basket-generate-proxy.json index 34f02bdc..964d0384 100644 --- a/services/basket/src/EShopOnAbp.BasketService.HttpApi.Client/ClientProxies/basket-generate-proxy.json +++ b/services/basket/src/EShopOnAbp.BasketService.HttpApi.Client/ClientProxies/basket-generate-proxy.json @@ -75,6 +75,21 @@ "allowAnonymous": null, "implementFrom": "EShopOnAbp.BasketService.IBasketAppService" }, + "MergeBasketsAsync": { + "uniqueName": "MergeBasketsAsync", + "name": "MergeBasketsAsync", + "httpMethod": "POST", + "url": "api/basket/basket/merge-baskets", + "supportedVersions": [], + "parametersOnMethod": [], + "parameters": [], + "returnValue": { + "type": "EShopOnAbp.BasketService.BasketDto", + "typeSimple": "EShopOnAbp.BasketService.BasketDto" + }, + "allowAnonymous": null, + "implementFrom": "EShopOnAbp.BasketService.IBasketAppService" + }, "AddProductAsyncByInput": { "uniqueName": "AddProductAsyncByInput", "name": "AddProductAsync", From fec82532e297126ebd35a68c7baaf5db5f6e1763 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 23 Dec 2021 13:47:10 +0300 Subject: [PATCH 4/9] removed cookie constant --- apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js | 2 +- shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js index 9af51771..04c54ef9 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/index.js @@ -1,6 +1,6 @@ (function () { //set anonymous user - let anonymousId = abp.utils.getCookieValue("eshop_anonymousId"); + let anonymousId = abp.utils.getCookieValue("anonymous_id"); if (anonymousId != null) { console.info("Anonymous user set:" + anonymousId); } diff --git a/shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs b/shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs index 87a36a2f..2e023cea 100644 --- a/shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs +++ b/shared/EShopOnAbp.Shared.Hosting.AspNetCore/EShopConstants.cs @@ -2,6 +2,6 @@ public static class EShopConstants { - public const string AnonymousUserCookieName = "eshop_anonymousId"; + // public const string AnonymousUserCookieName = "eshop_anonymousId"; public const string AnonymousUserClaimName = "anonymous_id"; } \ No newline at end of file From ed47cb47f753c3ae426f44bf81d101f8063e707e Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 23 Dec 2021 13:47:21 +0300 Subject: [PATCH 5/9] added logging for diagnose --- .../EShopUserClaimsPrincipalFactory.cs | 17 +++++++-- .../Basket/UserBasketProvider.cs | 35 +++++++++++++------ .../EShopOnAbpPublicWebModule.cs | 2 ++ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs index db519d7c..8d6a5539 100644 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs @@ -41,14 +41,25 @@ public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory public override async Task CreateAsync(IdentityUser user) { var principal = await base.CreateAsync(user); - if (HttpContext.Request.Cookies.ContainsKey(EShopConstants.AnonymousUserCookieName)) - { - HttpContext.Request.Cookies.TryGetValue(EShopConstants.AnonymousUserCookieName, out var anonymousUserId); + // if (HttpContext.Request.Cookies.ContainsKey(EShopConstants.AnonymousUserClaimName)) + // { + HttpContext.Request.Cookies.TryGetValue(EShopConstants.AnonymousUserClaimName, out var anonymousUserId); principal.Identities.First() .AddClaim(new Claim(EShopConstants.AnonymousUserClaimName, anonymousUserId)); _logger.LogInformation( $"Added {EShopConstants.AnonymousUserClaimName} claim of AnonymousUserId from cookies:{anonymousUserId}"); + // } + + // You can notice that cookie contains anonymous_id + foreach (var cookie in HttpContext.Request.Cookies.ToList()) + { + _logger.LogInformation($"key:{cookie.Key} - value:{cookie.Value}"); + } + _logger.LogInformation($"===================="); + foreach (var claim in principal.Claims.ToList()) + { + _logger.LogInformation($"key:{claim.Type} - value:{claim.Value}"); } return principal; diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Basket/UserBasketProvider.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/Basket/UserBasketProvider.cs index 2fd7e5de..df7fc7d5 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Basket/UserBasketProvider.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Basket/UserBasketProvider.cs @@ -1,12 +1,11 @@ -using Castle.Core.Logging; -using EShopOnAbp.BasketService; +using EShopOnAbp.BasketService; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; +using EShopOnAbp.Shared.Hosting.AspNetCore; +using Microsoft.AspNetCore.Authentication; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.Users; @@ -41,8 +40,10 @@ namespace EShopOnAbp.PublicWeb.Basket { try { + var access_token = await HttpContext.GetTokenAsync("access_token"); + logger.LogInformation($"ACCESS_TOKEN:{access_token}"); // Get anonymous user id from cookie - HttpContext.Request.Cookies.TryGetValue(CookieConstants.AnonymousUserCookieName, + HttpContext.Request.Cookies.TryGetValue(EShopConstants.AnonymousUserClaimName, out string anonymousUserId); logger.LogInformation($"========= Anonymous User Id from Cookie:{anonymousUserId} ========= "); @@ -50,8 +51,13 @@ namespace EShopOnAbp.PublicWeb.Basket if (string.IsNullOrEmpty(anonymousUserId)) { anonymousUserId = guidGenerator.Create().ToString(); - HttpContext.Response.Cookies.Append(CookieConstants.AnonymousUserCookieName, anonymousUserId); - logger.LogInformation($"========= Generated new User Id:{anonymousUserId} ========= APPENDED TO COOKIE ====== "); + HttpContext.Response.Cookies.Append(EShopConstants.AnonymousUserClaimName, anonymousUserId, + new CookieOptions + { + SameSite = SameSiteMode.Lax + }); + logger.LogInformation( + $"========= Generated new User Id:{anonymousUserId} ========= APPENDED TO COOKIE ====== "); } if (!currentUser.IsAuthenticated) @@ -60,11 +66,20 @@ namespace EShopOnAbp.PublicWeb.Basket $"========= Get Basket for Anonymous UserId:{anonymousUserId} ========= APPENDED TO COOKIE ====== "); return await basketAppService.GetByAnonymousUserIdAsync(Guid.Parse(anonymousUserId)); } - else + + //TODO: Merge with anonymously stored cart if exist + var userClaimValue = currentUser.FindClaimValue(EShopConstants.AnonymousUserClaimName); + foreach (var claim in currentUser.GetAllClaims()) + { + logger.LogInformation($"Claim Type:{claim.Type}-Value:{claim.Value}"); + } + + if (string.IsNullOrEmpty(userClaimValue)) { - //TODO: Merge with anonymously stored cart if exist return await basketAppService.GetAsync(); } + + return await basketAppService.MergeBasketsAsync(); } catch (Exception ex) { @@ -73,4 +88,4 @@ namespace EShopOnAbp.PublicWeb.Basket } } } -} +} \ No newline at end of file diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPublicWebModule.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPublicWebModule.cs index d912d267..a3a83f9c 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPublicWebModule.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPublicWebModule.cs @@ -110,6 +110,8 @@ namespace EShopOnAbp.PublicWeb options.Scope.Add("AdministrationService"); options.Scope.Add("BasketService"); options.Scope.Add("CatalogService"); + + options.ClaimActions.MapUniqueJsonKey(EShopConstants.AnonymousUserClaimName, EShopConstants.AnonymousUserClaimName); }); var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); From 0fe67181204a2b76b9ceac2267d9e19f17d02537 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 23 Dec 2021 14:15:42 +0300 Subject: [PATCH 6/9] added AnonymousUserProvider --- .../AnonymousUserProvider.cs | 8 +++++ .../EShopUserClaimsPrincipalFactory.cs | 32 ++++++++----------- 2 files changed, 21 insertions(+), 19 deletions(-) create mode 100644 apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserProvider.cs diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserProvider.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserProvider.cs new file mode 100644 index 00000000..ac31ad7e --- /dev/null +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserProvider.cs @@ -0,0 +1,8 @@ +using Volo.Abp.DependencyInjection; + +namespace EShopOnAbp.AuthServer; + +public class AnonymousUserProvider : ISingletonDependency +{ + public string AnonymousUserId { get; set; } +} \ No newline at end of file diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs index 8d6a5539..9c0d2393 100644 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs @@ -20,6 +20,7 @@ public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory { private readonly IHttpContextAccessor _httpContextAccessor; private readonly ILogger _logger; + private readonly AnonymousUserProvider _anonymousUserProvider; protected HttpContext HttpContext => _httpContextAccessor.HttpContext; public EShopUserClaimsPrincipalFactory( @@ -28,7 +29,9 @@ public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory IOptions options, ICurrentPrincipalAccessor currentPrincipalAccessor, IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory, - IHttpContextAccessor httpContextAccessor, ILogger logger) : base(userManager, + IHttpContextAccessor httpContextAccessor, + ILogger logger, + AnonymousUserProvider anonymousUserProvider) : base(userManager, roleManager, options, currentPrincipalAccessor, @@ -36,31 +39,22 @@ public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory { _httpContextAccessor = httpContextAccessor; _logger = logger; + _anonymousUserProvider = anonymousUserProvider; } public override async Task CreateAsync(IdentityUser user) { var principal = await base.CreateAsync(user); - // if (HttpContext.Request.Cookies.ContainsKey(EShopConstants.AnonymousUserClaimName)) - // { - HttpContext.Request.Cookies.TryGetValue(EShopConstants.AnonymousUserClaimName, out var anonymousUserId); - - principal.Identities.First() - .AddClaim(new Claim(EShopConstants.AnonymousUserClaimName, anonymousUserId)); - _logger.LogInformation( - $"Added {EShopConstants.AnonymousUserClaimName} claim of AnonymousUserId from cookies:{anonymousUserId}"); - // } - - // You can notice that cookie contains anonymous_id - foreach (var cookie in HttpContext.Request.Cookies.ToList()) + if (HttpContext.Request.Cookies.ContainsKey(EShopConstants.AnonymousUserClaimName)) { - _logger.LogInformation($"key:{cookie.Key} - value:{cookie.Value}"); - } - _logger.LogInformation($"===================="); - foreach (var claim in principal.Claims.ToList()) - { - _logger.LogInformation($"key:{claim.Type} - value:{claim.Value}"); + HttpContext.Request.Cookies.TryGetValue(EShopConstants.AnonymousUserClaimName, out var anonymousUserId); + _anonymousUserProvider.AnonymousUserId = anonymousUserId; } + + principal.Identities.First() + .AddClaim(new Claim(EShopConstants.AnonymousUserClaimName, _anonymousUserProvider.AnonymousUserId)); + _logger.LogInformation( + $"Added {EShopConstants.AnonymousUserClaimName} claim of AnonymousUserId from cookies:{_anonymousUserProvider.AnonymousUserId}"); return principal; } From 671fff720a557834e16cdfd81148c731b8e80242 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Thu, 23 Dec 2021 17:15:18 +0300 Subject: [PATCH 7/9] Added caching for anonymous user id --- .../AnonymousUserItem.cs | 6 ++++ .../AnonymousUserProvider.cs | 8 ----- .../EShopOnAbpAuthServerModule.cs | 2 ++ .../EShopUserClaimsPrincipalFactory.cs | 30 ++++++++++++------- .../Basket/UserBasketProvider.cs | 14 +++++---- .../EShopOnAbpPublicWebModule.cs | 2 -- .../BasketAppService.cs | 4 --- 7 files changed, 36 insertions(+), 30 deletions(-) create mode 100644 apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserItem.cs delete mode 100644 apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserProvider.cs diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserItem.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserItem.cs new file mode 100644 index 00000000..3679543d --- /dev/null +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserItem.cs @@ -0,0 +1,6 @@ +namespace EShopOnAbp.AuthServer; + +public class AnonymousUserItem +{ + public string AnonymousUserId { get; set; } +} \ No newline at end of file diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserProvider.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserProvider.cs deleted file mode 100644 index ac31ad7e..00000000 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/AnonymousUserProvider.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Volo.Abp.DependencyInjection; - -namespace EShopOnAbp.AuthServer; - -public class AnonymousUserProvider : ISingletonDependency -{ - public string AnonymousUserId { get; set; } -} \ No newline at end of file diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs index bcaf4c74..4e4897e4 100644 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs @@ -99,6 +99,8 @@ namespace EShopOnAbp.AuthServer options.IsEnabled = true; }); + // context.Services.Replace(ServiceDescriptor.Transient()); + Configure(options => { diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs index 9c0d2393..32d0e1fc 100644 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserClaimsPrincipalFactory.cs @@ -1,11 +1,14 @@ -using System.Linq; +using System; +using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using EShopOnAbp.Shared.Hosting.AspNetCore; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Volo.Abp.Caching; using Volo.Abp.DependencyInjection; using Volo.Abp.Identity; using Volo.Abp.Security.Claims; @@ -20,7 +23,7 @@ public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory { private readonly IHttpContextAccessor _httpContextAccessor; private readonly ILogger _logger; - private readonly AnonymousUserProvider _anonymousUserProvider; + private readonly IDistributedCache _cache; protected HttpContext HttpContext => _httpContextAccessor.HttpContext; public EShopUserClaimsPrincipalFactory( @@ -29,9 +32,9 @@ public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory IOptions options, ICurrentPrincipalAccessor currentPrincipalAccessor, IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory, - IHttpContextAccessor httpContextAccessor, - ILogger logger, - AnonymousUserProvider anonymousUserProvider) : base(userManager, + IHttpContextAccessor httpContextAccessor, + ILogger logger, + IDistributedCache cache) : base(userManager, roleManager, options, currentPrincipalAccessor, @@ -39,7 +42,7 @@ public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory { _httpContextAccessor = httpContextAccessor; _logger = logger; - _anonymousUserProvider = anonymousUserProvider; + _cache = cache; } public override async Task CreateAsync(IdentityUser user) @@ -48,13 +51,18 @@ public class EShopUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory if (HttpContext.Request.Cookies.ContainsKey(EShopConstants.AnonymousUserClaimName)) { HttpContext.Request.Cookies.TryGetValue(EShopConstants.AnonymousUserClaimName, out var anonymousUserId); - _anonymousUserProvider.AnonymousUserId = anonymousUserId; + + await _cache.SetAsync(user.Id, new AnonymousUserItem {AnonymousUserId = anonymousUserId}, options: new DistributedCacheEntryOptions() + { + AbsoluteExpiration = DateTimeOffset.UtcNow.AddSeconds(60) + }); + _logger.LogInformation($"Cached anonymousUserId:{anonymousUserId}."); } - + + var cachedItem = await _cache.GetAsync(user.Id); + _logger.LogInformation($"Retrieved anonymousUserId:{cachedItem.AnonymousUserId} from cache."); principal.Identities.First() - .AddClaim(new Claim(EShopConstants.AnonymousUserClaimName, _anonymousUserProvider.AnonymousUserId)); - _logger.LogInformation( - $"Added {EShopConstants.AnonymousUserClaimName} claim of AnonymousUserId from cookies:{_anonymousUserProvider.AnonymousUserId}"); + .AddClaim(new Claim(EShopConstants.AnonymousUserClaimName, cachedItem.AnonymousUserId)); return principal; } diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Basket/UserBasketProvider.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/Basket/UserBasketProvider.cs index df7fc7d5..be4171d5 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Basket/UserBasketProvider.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Basket/UserBasketProvider.cs @@ -42,6 +42,9 @@ namespace EShopOnAbp.PublicWeb.Basket { var access_token = await HttpContext.GetTokenAsync("access_token"); logger.LogInformation($"ACCESS_TOKEN:{access_token}"); + logger.LogInformation($"*********************"); + var id_token = await HttpContext.GetTokenAsync("id_token"); + logger.LogInformation($"ID_TOKEN:{id_token}"); // Get anonymous user id from cookie HttpContext.Request.Cookies.TryGetValue(EShopConstants.AnonymousUserClaimName, out string anonymousUserId); @@ -51,11 +54,12 @@ namespace EShopOnAbp.PublicWeb.Basket if (string.IsNullOrEmpty(anonymousUserId)) { anonymousUserId = guidGenerator.Create().ToString(); - HttpContext.Response.Cookies.Append(EShopConstants.AnonymousUserClaimName, anonymousUserId, - new CookieOptions - { - SameSite = SameSiteMode.Lax - }); + HttpContext.Response.Cookies.Append(EShopConstants.AnonymousUserClaimName, anonymousUserId + // , new CookieOptions + // { + // SameSite = SameSiteMode.Lax + // } + ); logger.LogInformation( $"========= Generated new User Id:{anonymousUserId} ========= APPENDED TO COOKIE ====== "); } diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPublicWebModule.cs b/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPublicWebModule.cs index a3a83f9c..d912d267 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPublicWebModule.cs +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/EShopOnAbpPublicWebModule.cs @@ -110,8 +110,6 @@ namespace EShopOnAbp.PublicWeb options.Scope.Add("AdministrationService"); options.Scope.Add("BasketService"); options.Scope.Add("CatalogService"); - - options.ClaimActions.MapUniqueJsonKey(EShopConstants.AnonymousUserClaimName, EShopConstants.AnonymousUserClaimName); }); var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); diff --git a/services/basket/src/EShopOnAbp.BasketService.Application/BasketAppService.cs b/services/basket/src/EShopOnAbp.BasketService.Application/BasketAppService.cs index 6ae2f72b..f2280018 100644 --- a/services/basket/src/EShopOnAbp.BasketService.Application/BasketAppService.cs +++ b/services/basket/src/EShopOnAbp.BasketService.Application/BasketAppService.cs @@ -45,10 +45,6 @@ public class BasketAppService : BasketServiceAppService, IBasketAppService //TODO: move to custom shared project var anonymousUserIdString = CurrentUser.FindClaimValue("anonymous_id"); - foreach (var claim in CurrentUser.GetAllClaims()) - { - Logger.LogInformation($"claim type:{ claim.Type} - value:{claim.Value}"); - } if (!Guid.TryParse(anonymousUserIdString, out Guid anonymousUserId)) { Logger.LogError($"Couldn't parse anonymous Id from claim!{anonymousUserIdString}"); From e7cd826fcce0daae6adc82788f42448f8c3cf513 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Fri, 24 Dec 2021 11:21:18 +0300 Subject: [PATCH 8/9] fixed cookie name --- .../EShopOnAbp.PublicWeb/wwwroot/components/basket-widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/basket-widget.js b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/basket-widget.js index c71356ba..40abc2e9 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/basket-widget.js +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/wwwroot/components/basket-widget.js @@ -1,6 +1,6 @@ (function () { - let anonymousId = abp.utils.getCookieValue("eshop_anonymousId"); + let anonymousId = abp.utils.getCookieValue("anonymous_id"); abp.widgets.BasketWidget = function ($wrapper) { From a95434046c78245bd93fa4621572baa24b1a67be Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Fri, 24 Dec 2021 11:23:06 +0300 Subject: [PATCH 9/9] Updated basket page layout --- .../Components/Basket/Default.cshtml | 61 +++++++++++-------- .../EShopOnAbp.PublicWeb/Pages/Basket.cshtml | 7 ++- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Basket/Default.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Basket/Default.cshtml index e0057a76..05bbe1da 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Basket/Default.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Components/Basket/Default.cshtml @@ -1,4 +1,3 @@ - @using EShopOnAbp.Localization @using Microsoft.Extensions.Localization @@ -10,38 +9,50 @@ @if (!Model.Items.Any()) {
-

Your basket is empty. Click to a product to add it!

+

+ + Your basket is empty. Click to a product to add it! + +

} else { -
- @foreach (var item in Model.Items) - { -
- @if (!item.ImageName.IsNullOrEmpty()) - { - - } - else +
+
+
+ @foreach (var item in Model.Items) { - +
+ @if (!item.ImageName.IsNullOrEmpty()) + { + + } + else + { + + } + @item.ProductName + @if (item.Count > 1) + { + (@("x" + item.Count)) + } + - $@item.TotalPrice.ToString("0.00") + +
} - @item.ProductName - @if (item.Count > 1) - { - (@("x" + item.Count)) - } - - $@item.TotalPrice.ToString("0.00") - +
+
+ @L["Total"]: $@Model.TotalPrice.ToString("0.00") +
- } -
-
- @L["Total"]: $@Model.TotalPrice.ToString("0.00")
-
- +
+

Total Selected (@Model.Items.Count)

+

$@Model.TotalPrice.ToString("0.00")

+
+ +
} diff --git a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Basket.cshtml b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Basket.cshtml index e30d044d..4545fae1 100644 --- a/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Basket.cshtml +++ b/apps/public-web/src/EShopOnAbp.PublicWeb/Pages/Basket.cshtml @@ -5,15 +5,16 @@ @model EShopOnAbp.PublicWeb.Pages.Basket @section scripts { - - + + } @inject IStringLocalizer L -
+

@L["YourBasket"]

@await Component.InvokeAsync(typeof(BasketWidgetViewComponent))
+
\ No newline at end of file