From 98752ab41e546ab203b7f3ae028608337199e130 Mon Sep 17 00:00:00 2001 From: "cristian.cifuentes" Date: Tue, 13 Feb 2024 14:45:18 -0500 Subject: [PATCH 1/7] Fix: authetication quieries and mutations --- dotnet/GraphQL/Mutation.cs | 31 +----- dotnet/Services/WishListService.cs | 165 ++++++++++++++++++++--------- 2 files changed, 121 insertions(+), 75 deletions(-) diff --git a/dotnet/GraphQL/Mutation.cs b/dotnet/GraphQL/Mutation.cs index a299009..0b3dae5 100644 --- a/dotnet/GraphQL/Mutation.cs +++ b/dotnet/GraphQL/Mutation.cs @@ -19,7 +19,7 @@ public Mutation(IWishListService wishListService) { Name = "Mutation"; - FieldAsync( + Field( "addToList", arguments: new QueryArguments( new QueryArgument> { Name = "listItem" }, @@ -27,19 +27,8 @@ public Mutation(IWishListService wishListService) new QueryArgument { Name = "name" }, new QueryArgument { Name = "public" } ), - resolve: async context => + resolve: context => { - - HttpStatusCode isValidAuthUser = await wishListService.IsValidAuthUser(); - if (isValidAuthUser != HttpStatusCode.OK) - { - context.Errors.Add(new ExecutionError(isValidAuthUser.ToString()) - { - Code = isValidAuthUser.ToString() - }); - - return null; - } var listItem = context.GetArgument("listItem"); string shopperId = context.GetArgument("shopperId"); @@ -49,28 +38,16 @@ public Mutation(IWishListService wishListService) return wishListService.SaveItem(listItem, shopperId, listName, isPublic); }); - FieldAsync( + Field( "removeFromList", arguments: new QueryArguments( new QueryArgument> { Name = "id" }, new QueryArgument> { Name = "shopperId" }, new QueryArgument { Name = "name" } ), - resolve: async context => + resolve: context => { - HttpStatusCode isValidAuthUser = await wishListService.IsValidAuthUser(); - - if (isValidAuthUser != HttpStatusCode.OK) - { - context.Errors.Add(new ExecutionError(isValidAuthUser.ToString()) - { - Code = isValidAuthUser.ToString() - }); - - return null; - } - int id = context.GetArgument("id"); string shopperId = context.GetArgument("shopperId"); string listName = context.GetArgument("name"); diff --git a/dotnet/Services/WishListService.cs b/dotnet/Services/WishListService.cs index c55c511..8c59f1b 100644 --- a/dotnet/Services/WishListService.cs +++ b/dotnet/Services/WishListService.cs @@ -102,81 +102,150 @@ public async Task SaveList(IList listItems, string shopperId, st public async Task SaveItem(ListItem listItem, string shopperId, string listName, bool? isPublic) { - IList listItemsToSave = null; - WishListWrapper wishListWrapper = await this.GetList(shopperId, listName); - ListItemsWrapper listItemsWrapper = wishListWrapper.ListItemsWrapper.FirstOrDefault(); - if (listItemsWrapper != null && listItemsWrapper.ListItems != null) + if (string.IsNullOrEmpty(_context.Vtex.StoreUserAuthToken)) { - _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' {listItemsWrapper.ListItems.Count} existing items."); - listItemsToSave = listItemsWrapper.ListItems; - foreach (ListItem item in listItemsToSave) + return null; + } + + ValidatedUser validatedUser = null; + + try { + validatedUser = await ValidateUserToken(_context.Vtex.StoreUserAuthToken); + } + catch (Exception ex) + { + _context.Vtex.Logger.Error("IsValidAuthUser", null, "Error fetching user", ex); + + return null; + } + + bool hasPermission = validatedUser != null && validatedUser.AuthStatus.Equals("Success"); + + if (!hasPermission) + { + _context.Vtex.Logger.Warn("IsValidAuthUser", null, "User Does Not Have Permission"); + + return null; + } + + if(hasPermission) { + + IList listItemsToSave = null; + + WishListWrapper wishListWrapper = await this.GetList(shopperId, listName); + ListItemsWrapper listItemsWrapper = wishListWrapper.ListItemsWrapper.FirstOrDefault(); + if (listItemsWrapper != null && listItemsWrapper.ListItems != null) { - if (listItem.ProductId == item.ProductId) + _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' {listItemsWrapper.ListItems.Count} existing items."); + listItemsToSave = listItemsWrapper.ListItems; + foreach (ListItem item in listItemsToSave) { - listItem.Id = item.Id; + if (listItem.ProductId == item.ProductId) + { + listItem.Id = item.Id; + } } - } - if(listItem.Id == null) - { - int maxId = 0; - if (listItemsToSave.Count > 0) + if(listItem.Id == null) { - maxId = listItemsToSave.Max(t => t.Id ?? 0); + int maxId = 0; + if (listItemsToSave.Count > 0) + { + maxId = listItemsToSave.Max(t => t.Id ?? 0); + } + + listItem.Id = ++maxId; + _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' Setting Id: {listItem.Id}"); + } + else + { + // If an Id has been specified, remove existing item + ListItem itemToRemove = listItemsToSave.Where(r => r.Id == listItem.Id).FirstOrDefault(); + if (itemToRemove != null && listItemsToSave.Remove(itemToRemove)) + { + _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' Removing {listItem.Id}"); + listItemsToSave.Remove(itemToRemove); + } } - listItem.Id = ++maxId; - _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' Setting Id: {listItem.Id}"); + listItemsToSave.Add(listItem); } else { - // If an Id has been specified, remove existing item - ListItem itemToRemove = listItemsToSave.Where(r => r.Id == listItem.Id).FirstOrDefault(); - if (itemToRemove != null && listItemsToSave.Remove(itemToRemove)) - { - _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' Removing {listItem.Id}"); - listItemsToSave.Remove(itemToRemove); - } + listItem.Id = listItem.Id ?? 0; + listItemsToSave = new List { listItem }; + _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' First Item: {listItem.Id}"); } - listItemsToSave.Add(listItem); + if(await _wishListRepository.SaveWishList(listItemsToSave, shopperId, listName, isPublic, wishListWrapper.Id)) + { + _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' Saved: {listItem.Id}"); + } + else + { + _context.Vtex.Logger.Warn("SaveItem", null, $"Saving '{shopperId}' '{listName}' Failed to save: {listItem.Id}"); + } + + return listItem.Id; + + } else { + return null; } - else + + + } + + public async Task RemoveItem(int itemId, string shopperId, string listName) + { + + if (string.IsNullOrEmpty(_context.Vtex.StoreUserAuthToken)) { - listItem.Id = listItem.Id ?? 0; - listItemsToSave = new List { listItem }; - _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' First Item: {listItem.Id}"); + return false; } - if(await _wishListRepository.SaveWishList(listItemsToSave, shopperId, listName, isPublic, wishListWrapper.Id)) - { - _context.Vtex.Logger.Debug("SaveItem", null, $"Saving '{shopperId}' '{listName}' Saved: {listItem.Id}"); + ValidatedUser validatedUser = null; + + try { + validatedUser = await ValidateUserToken(_context.Vtex.StoreUserAuthToken); } - else + catch (Exception ex) { - _context.Vtex.Logger.Warn("SaveItem", null, $"Saving '{shopperId}' '{listName}' Failed to save: {listItem.Id}"); + _context.Vtex.Logger.Error("IsValidAuthUser", null, "Error fetching user", ex); + + return false; } - return listItem.Id; - } + bool hasPermission = validatedUser != null && validatedUser.AuthStatus.Equals("Success"); - public async Task RemoveItem(int itemId, string shopperId, string listName) - { - bool wasRemoved = false; - IList listItemsToSave = null; - WishListWrapper wishListWrapper = await this.GetList(shopperId, listName); - ListItemsWrapper listItemsWrapper = wishListWrapper.ListItemsWrapper.FirstOrDefault(); - if (listItemsWrapper != null && listItemsWrapper.ListItems != null) + if (!hasPermission) { - listItemsToSave = listItemsWrapper.ListItems; - ListItem itemToRemove = listItemsToSave.FirstOrDefault(r => r.Id == itemId); - if (itemToRemove != null && listItemsToSave.Remove(itemToRemove)) + _context.Vtex.Logger.Warn("IsValidAuthUser", null, "User Does Not Have Permission"); + + return false; + } + + if(hasPermission) { + + bool wasRemoved = false; + IList listItemsToSave = null; + WishListWrapper wishListWrapper = await this.GetList(shopperId, listName); + ListItemsWrapper listItemsWrapper = wishListWrapper.ListItemsWrapper.FirstOrDefault(); + if (listItemsWrapper != null && listItemsWrapper.ListItems != null) { - wasRemoved = await _wishListRepository.SaveWishList(listItemsToSave, shopperId, listName, listItemsWrapper.IsPublic, wishListWrapper.Id); + listItemsToSave = listItemsWrapper.ListItems; + ListItem itemToRemove = listItemsToSave.FirstOrDefault(r => r.Id == itemId); + if (itemToRemove != null && listItemsToSave.Remove(itemToRemove)) + { + wasRemoved = await _wishListRepository.SaveWishList(listItemsToSave, shopperId, listName, listItemsWrapper.IsPublic, wishListWrapper.Id); + } } + + return wasRemoved; + + } else { + return false; } - return wasRemoved; } public async Task> LimitList(IList listItems, int from, int to) From af5580e60fb8a4c5834125022c58dc1b30ad81fb Mon Sep 17 00:00:00 2001 From: "cristian.cifuentes" Date: Wed, 14 Feb 2024 13:16:03 -0500 Subject: [PATCH 2/7] Release v1.16.4-beta.0 --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 608a608..31a8718 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "name": "wish-list", "vendor": "vtex", - "version": "1.16.3", + "version": "1.16.4-beta.0", "title": "Wish List", "description": "The Wishlist app is designed for B2C. It adds a heart icon to the Shelfs and Product Page, so the user can add it to the Wishlist, you can list all the Wishlisted items at /wishlist", "categories": [], From 8334f825e671aa8afe53f4e8e2a8c2fbb62044e5 Mon Sep 17 00:00:00 2001 From: "cristian.cifuentes" Date: Wed, 14 Feb 2024 13:20:42 -0500 Subject: [PATCH 3/7] Release v1.16.5-beta.0 --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 31a8718..6ccca46 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "name": "wish-list", "vendor": "vtex", - "version": "1.16.4-beta.0", + "version": "1.16.5-beta.0", "title": "Wish List", "description": "The Wishlist app is designed for B2C. It adds a heart icon to the Shelfs and Product Page, so the user can add it to the Wishlist, you can list all the Wishlisted items at /wishlist", "categories": [], From e49216491b8cca976538364b5367afece8ee4fe7 Mon Sep 17 00:00:00 2001 From: "cristian.cifuentes" Date: Mon, 19 Feb 2024 11:57:53 -0500 Subject: [PATCH 4/7] Add comments Changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b66b977..915a606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Fixed +- Authentication to queries and mutation fixed + ### Added - Authentication yo queries and mutation added From 4a185901685047372ab48b4ef5e26b5dce22e11b Mon Sep 17 00:00:00 2001 From: "cristian.cifuentes" Date: Tue, 20 Feb 2024 09:59:47 -0500 Subject: [PATCH 5/7] remove workflow files --- .github/workflows/qe-dispatch.yml | 23 ------------- .github/workflows/qe-pull-request-target.yml | 31 ------------------ .github/workflows/qe-pull-request.yml | 34 -------------------- .github/workflows/qe-push.yml | 25 -------------- .github/workflows/qe-schedule.yml | 15 --------- 5 files changed, 128 deletions(-) delete mode 100644 .github/workflows/qe-dispatch.yml delete mode 100644 .github/workflows/qe-pull-request-target.yml delete mode 100644 .github/workflows/qe-pull-request.yml delete mode 100644 .github/workflows/qe-push.yml delete mode 100644 .github/workflows/qe-schedule.yml diff --git a/.github/workflows/qe-dispatch.yml b/.github/workflows/qe-dispatch.yml deleted file mode 100644 index 6656b3f..0000000 --- a/.github/workflows/qe-dispatch.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: '[DSP] Quality Engineering' - -on: - workflow_dispatch: - inputs: - cyRunnerBranch: - description: 'Which branch to use on Cy-Runner?' - default: 'main' - cyRunnerTimeOut: - description: 'Wait how much time (in minutes) for the job to complete?' - default: '30' - -jobs: - quality-engineering: - name: QE - uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 - with: - cypress: true - cyRunnerBranch: ${{ inputs.cyRunnerBranch }} - cyRunnerTimeOut: ${{ fromJSON(github.event.inputs.cyRunnerTimeOut) }} - secrets: - githubToken: ${{ secrets.GITHUB_TOKEN }} - cypressJson: ${{ secrets.VTEX_QE }} diff --git a/.github/workflows/qe-pull-request-target.yml b/.github/workflows/qe-pull-request-target.yml deleted file mode 100644 index b5d077a..0000000 --- a/.github/workflows/qe-pull-request-target.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: '[PRT] Quality Engineering' - -on: - pull_request_target: - branches: - - main - - master - types: - - labeled - -jobs: - quality-engineering: - name: QE - uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 - with: - danger: true - dangerRequireChangelog: false - nodeLint: true - reactTest: false - nodeSonar: true - nodeSonarProjectKey: vtex-apps_wish-list-ts - nodeSonarOrganization: vtex-apps - dotnetLint: true - dotnetSonar: true - dotnetSonarProjectKey: vtex-apps_wish-list-dotnet - dotnetSonarOrganization: vtex-apps - cypress: true - secrets: - githubToken: ${{ secrets.GITHUB_TOKEN }} - sonarToken: ${{ secrets.SONAR_TOKEN }} - cypressJson: ${{ secrets.VTEX_QE }} diff --git a/.github/workflows/qe-pull-request.yml b/.github/workflows/qe-pull-request.yml deleted file mode 100644 index c7757d6..0000000 --- a/.github/workflows/qe-pull-request.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: '[PRN] Quality Engineering' - -on: - pull_request: - branches: - - main - - master - types: - - opened - - synchronize - - reopened - - ready_for_review - -jobs: - quality-engineering: - name: QE - uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 - with: - danger: true - dangerRequireChangelog: false - nodeLint: true - reactTest: false - nodeSonar: true - nodeSonarProjectKey: vtex-apps_wish-list-ts - nodeSonarOrganization: vtex-apps - dotnetLint: true - dotnetSonar: true - dotnetSonarProjectKey: vtex-apps_wish-list-dotnet - dotnetSonarOrganization: vtex-apps - cypress: true - secrets: - githubToken: ${{ secrets.GITHUB_TOKEN }} - sonarToken: ${{ secrets.SONAR_TOKEN }} - cypressJson: ${{ secrets.VTEX_QE }} diff --git a/.github/workflows/qe-push.yml b/.github/workflows/qe-push.yml deleted file mode 100644 index 7d7a727..0000000 --- a/.github/workflows/qe-push.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: '[PSH] Quality Engineering' - -on: - push: - branches: - - master - - main - -jobs: - quality-engineering: - name: QE - uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 - with: - nodeLint: true - nodeTest: false - nodeSonar: true - nodeSonarProjectKey: vtex-apps_wish-list-ts - nodeSonarOrganization: vtex-apps - dotnetLint: true - dotnetSonar: true - dotnetSonarProjectKey: vtex-apps_wish-list-dotnet - dotnetSonarOrganization: vtex-apps - secrets: - githubToken: ${{ secrets.GITHUB_TOKEN }} - sonarToken: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/qe-schedule.yml b/.github/workflows/qe-schedule.yml deleted file mode 100644 index e15c502..0000000 --- a/.github/workflows/qe-schedule.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: '[SCH] Quality Engineering' - -on: - schedule: - - cron: '0 9 * * MON-FRI' - -jobs: - quality-engineering: - name: QE - uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 - with: - cypress: true - secrets: - githubToken: ${{ secrets.GITHUB_TOKEN }} - cypressJson: ${{ secrets.VTEX_QE }} From 15083d3c94f95ea4b57b936502d58ceaa602392a Mon Sep 17 00:00:00 2001 From: "cristian.cifuentes" Date: Tue, 20 Feb 2024 11:20:41 -0500 Subject: [PATCH 6/7] manifest version --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 6ccca46..9d021bb 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "name": "wish-list", "vendor": "vtex", - "version": "1.16.5-beta.0", + "version": "1.16.4", "title": "Wish List", "description": "The Wishlist app is designed for B2C. It adds a heart icon to the Shelfs and Product Page, so the user can add it to the Wishlist, you can list all the Wishlisted items at /wishlist", "categories": [], From 5c071c7bb1ed22ae2b78dccd963369f092ddf3f9 Mon Sep 17 00:00:00 2001 From: "cristian.cifuentes" Date: Wed, 21 Feb 2024 11:16:56 -0500 Subject: [PATCH 7/7] add removed workflows --- .github/workflows/qe-dispatch.yml | 23 +++++++++++++++ .github/workflows/qe-pull-request-target.yml | 31 ++++++++++++++++++++ .github/workflows/qe-push.yml | 25 ++++++++++++++++ .github/workflows/qe-schedule.yml | 15 ++++++++++ 4 files changed, 94 insertions(+) create mode 100644 .github/workflows/qe-dispatch.yml create mode 100644 .github/workflows/qe-pull-request-target.yml create mode 100644 .github/workflows/qe-push.yml create mode 100644 .github/workflows/qe-schedule.yml diff --git a/.github/workflows/qe-dispatch.yml b/.github/workflows/qe-dispatch.yml new file mode 100644 index 0000000..6656b3f --- /dev/null +++ b/.github/workflows/qe-dispatch.yml @@ -0,0 +1,23 @@ +name: '[DSP] Quality Engineering' + +on: + workflow_dispatch: + inputs: + cyRunnerBranch: + description: 'Which branch to use on Cy-Runner?' + default: 'main' + cyRunnerTimeOut: + description: 'Wait how much time (in minutes) for the job to complete?' + default: '30' + +jobs: + quality-engineering: + name: QE + uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 + with: + cypress: true + cyRunnerBranch: ${{ inputs.cyRunnerBranch }} + cyRunnerTimeOut: ${{ fromJSON(github.event.inputs.cyRunnerTimeOut) }} + secrets: + githubToken: ${{ secrets.GITHUB_TOKEN }} + cypressJson: ${{ secrets.VTEX_QE }} diff --git a/.github/workflows/qe-pull-request-target.yml b/.github/workflows/qe-pull-request-target.yml new file mode 100644 index 0000000..b5d077a --- /dev/null +++ b/.github/workflows/qe-pull-request-target.yml @@ -0,0 +1,31 @@ +name: '[PRT] Quality Engineering' + +on: + pull_request_target: + branches: + - main + - master + types: + - labeled + +jobs: + quality-engineering: + name: QE + uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 + with: + danger: true + dangerRequireChangelog: false + nodeLint: true + reactTest: false + nodeSonar: true + nodeSonarProjectKey: vtex-apps_wish-list-ts + nodeSonarOrganization: vtex-apps + dotnetLint: true + dotnetSonar: true + dotnetSonarProjectKey: vtex-apps_wish-list-dotnet + dotnetSonarOrganization: vtex-apps + cypress: true + secrets: + githubToken: ${{ secrets.GITHUB_TOKEN }} + sonarToken: ${{ secrets.SONAR_TOKEN }} + cypressJson: ${{ secrets.VTEX_QE }} diff --git a/.github/workflows/qe-push.yml b/.github/workflows/qe-push.yml new file mode 100644 index 0000000..7d7a727 --- /dev/null +++ b/.github/workflows/qe-push.yml @@ -0,0 +1,25 @@ +name: '[PSH] Quality Engineering' + +on: + push: + branches: + - master + - main + +jobs: + quality-engineering: + name: QE + uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 + with: + nodeLint: true + nodeTest: false + nodeSonar: true + nodeSonarProjectKey: vtex-apps_wish-list-ts + nodeSonarOrganization: vtex-apps + dotnetLint: true + dotnetSonar: true + dotnetSonarProjectKey: vtex-apps_wish-list-dotnet + dotnetSonarOrganization: vtex-apps + secrets: + githubToken: ${{ secrets.GITHUB_TOKEN }} + sonarToken: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/qe-schedule.yml b/.github/workflows/qe-schedule.yml new file mode 100644 index 0000000..e15c502 --- /dev/null +++ b/.github/workflows/qe-schedule.yml @@ -0,0 +1,15 @@ +name: '[SCH] Quality Engineering' + +on: + schedule: + - cron: '0 9 * * MON-FRI' + +jobs: + quality-engineering: + name: QE + uses: vtex-apps/usqa/.github/workflows/quality-engineering.yml@v2 + with: + cypress: true + secrets: + githubToken: ${{ secrets.GITHUB_TOKEN }} + cypressJson: ${{ secrets.VTEX_QE }}