From 36e3eeecaac184bc3dbea4a4fd3709277372dd29 Mon Sep 17 00:00:00 2001 From: Umar Bolatov Date: Sun, 19 Jul 2020 14:22:26 -0700 Subject: [PATCH 01/65] Allow sorting apps by store, name or app type close #1568 --- BTCPayServer/Controllers/AppsController.cs | 35 ++++++++++++++++- BTCPayServer/Views/Apps/ListApps.cshtml | 45 ++++++++++++++++++++-- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/BTCPayServer/Controllers/AppsController.cs b/BTCPayServer/Controllers/AppsController.cs index 45496f7ee..ef756f1b1 100644 --- a/BTCPayServer/Controllers/AppsController.cs +++ b/BTCPayServer/Controllers/AppsController.cs @@ -47,9 +47,42 @@ namespace BTCPayServer.Controllers public string CreatedAppId { get; set; } - public async Task ListApps() + public async Task ListApps( + string sortOrder = null, + string sortOrderColumn = null + ) { var apps = await _AppService.GetAllApps(GetUserId()); + + if (sortOrder != null && sortOrderColumn != null) + { + apps = apps.OrderByDescending(app => + { + switch (sortOrderColumn) + { + case "Name": + return app.AppName; + case "Store": + return app.StoreName; + case "AppType": + return app.AppType; + default: + return app.Id; + } + }).ToArray(); + + switch (sortOrder) + { + case "desc": + ViewData[$"{sortOrderColumn}SortOrder"] = "asc"; + break; + case "asc": + apps = apps.Reverse().ToArray(); + ViewData[$"{sortOrderColumn}SortOrder"] = "desc"; + break; + } + } + return View(new ListAppsViewModel() { Apps = apps diff --git a/BTCPayServer/Views/Apps/ListApps.cshtml b/BTCPayServer/Views/Apps/ListApps.cshtml index a218a312b..51babba39 100644 --- a/BTCPayServer/Views/Apps/ListApps.cshtml +++ b/BTCPayServer/Views/Apps/ListApps.cshtml @@ -31,9 +31,48 @@ - - - + + + From 25527ec1dd99712d438353c4cb9cc9684514f24e Mon Sep 17 00:00:00 2001 From: Umar Bolatov Date: Mon, 20 Jul 2020 20:02:14 -0700 Subject: [PATCH 02/65] Use nameof() instead of strings --- BTCPayServer/Controllers/AppsController.cs | 6 +++--- BTCPayServer/Views/Apps/ListApps.cshtml | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/BTCPayServer/Controllers/AppsController.cs b/BTCPayServer/Controllers/AppsController.cs index ef756f1b1..3a788e384 100644 --- a/BTCPayServer/Controllers/AppsController.cs +++ b/BTCPayServer/Controllers/AppsController.cs @@ -60,11 +60,11 @@ namespace BTCPayServer.Controllers { switch (sortOrderColumn) { - case "Name": + case nameof(app.AppName): return app.AppName; - case "Store": + case nameof(app.StoreName): return app.StoreName; - case "AppType": + case nameof(app.AppType): return app.AppType; default: return app.Id; diff --git a/BTCPayServer/Views/Apps/ListApps.cshtml b/BTCPayServer/Views/Apps/ListApps.cshtml index 51babba39..4d296f6e6 100644 --- a/BTCPayServer/Views/Apps/ListApps.cshtml +++ b/BTCPayServer/Views/Apps/ListApps.cshtml @@ -34,28 +34,28 @@ From 967f28542fff2ce2038629f587bd314e72b7a59a Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Thu, 23 Jul 2020 09:45:40 +0200 Subject: [PATCH 03/65] Minor README improvements --- BTCPayServer.Tests/README.md | 28 +++++++++++++++++----------- README.md | 30 ++++++++++++++++++------------ 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/BTCPayServer.Tests/README.md b/BTCPayServer.Tests/README.md index 8ea5b0c25..6d7d00a61 100644 --- a/BTCPayServer.Tests/README.md +++ b/BTCPayServer.Tests/README.md @@ -1,31 +1,31 @@ # How to be started for development BTCPay Server tests depend on having a proper environment running with Postgres, Bitcoind, NBxplorer configured. -You can however use the `docker-compose.yml` of this folder to get it running. +You can however use the [`BTCPayServer.Tests/docker-compose.yml`](https://github.com/btcpayserver/btcpayserver/blob/master/BTCPayServer.Tests/docker-compose.yml) to get it running. In addition, when you run a debug session of BTCPay (Hitting F5 on Visual Studio Code or Visual Studio 2017), it will run the launch profile called `Docker-Regtest`. This launch profile depends on this `docker-compose` running. This is running a bitcoind instance on regtest, a private bitcoin blockchain for testing on which you can generate blocks yourself. -``` +```sh docker-compose up dev ``` You can run the tests while it is running through your favorite IDE, or with -``` +```sh dotnet test ``` Once you want to stop -``` +```sh docker-compose down ``` If you want to stop, and remove all existing data -``` +```sh docker-compose down --v ``` @@ -35,40 +35,46 @@ You can run tests on `MySql` database instead of `Postgres` by setting environne ### Using the test bitcoin-cli -You can call bitcoin-cli inside the container with `docker exec`, for example, if you want to send `0.23111090` to `mohu16LH66ptoWGEL1GtP6KHTBJYXMWhEf`: -``` +You can call bitcoin-cli inside the container with `docker exec`. +For example, if you want to send `0.23111090` to `mohu16LH66ptoWGEL1GtP6KHTBJYXMWhEf`: + +```sh ./docker-bitcoin-cli.sh sendtoaddress "mohu16LH66ptoWGEL1GtP6KHTBJYXMWhEf" 0.23111090 ``` If you are using Powershell: + ```powershell .\docker-bitcoin-cli.ps1 sendtoaddress "mohu16LH66ptoWGEL1GtP6KHTBJYXMWhEf" 0.23111090 ``` You can also generate blocks: + ```powershell .\docker-bitcoin-generate.ps1 3 ``` ### Using the test litecoin-cli -Same as bitcoin-cli, but with `.\docker-litecoin-cli.ps1` and `.\docker-litecoin-cli.sh` instead. +Same as bitcoin-cli, but with `.\docker-litecoin-cli.ps1` and `.\docker-litecoin-cli.sh` instead. ### Using the test lightning-cli If you are using Linux: -``` + +```sh ./docker-customer-lightning-cli.sh pay lnbcrt100u1pd2e6uspp5ajnadvhazjrz55twd5k6yeg9u87wpw0q2fdr7g960yl5asv5fmnqdq9d3hkccqpxmedyrk0ehw5ueqx5e0r4qrrv74cewddfcvsxaawqz7634cmjj39sqwy5tvhz0hasktkk6t9pqfdh3edmf3z09zst5y7khv3rvxh8ctqqw6mwhh ``` If you are using Powershell: -``` + +```powershell .\docker-customer-lightning-cli.ps1 pay lnbcrt100u1pd2e6uspp5ajnadvhazjrz55twd5k6yeg9u87wpw0q2fdr7g960yl5asv5fmnqdq9d3hkccqpxmedyrk0ehw5ueqx5e0r4qrrv74cewddfcvsxaawqz7634cmjj39sqwy5tvhz0hasktkk6t9pqfdh3edmf3z09zst5y7khv3rvxh8ctqqw6mwhh ``` If you get this message: -``` +```json { "code" : 205, "message" : "Could not find a route", "data" : { "getroute_tries" : 1, "sendpay_tries" : 0 } } ``` diff --git a/README.md b/README.md index 8a9bc7ea2..326af7c3c 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ After successful deployment, make sure to check our [getting started](https://do ## Documentation -Please check out our [official website](https://btcpayserver.org/), our [complete documentation](https://github.com/btcpayserver/btcpayserver-doc) and [FAQ](https://docs.btcpayserver.org/FAQ/) for more details. +Please check out our [official website](https://btcpayserver.org/), our [complete documentation](https://docs.btcpayserver.org/) and [FAQ](https://docs.btcpayserver.org/FAQ/) for more details. If you have trouble using BTCPay, consider joining [communities listed on official website](https://btcpayserver.org/#communityCTA) to get help from BTCPay community members. Only file [Github issue](https://github.com/btcpayserver/btcpayserver/issues) for technical issues you can't resolve through other channels or feature requests you've validated with other members of community. @@ -79,13 +79,14 @@ If you're a developer looking to help, but you're not sure where to begin, check Contributors looking to do something a bit more challenging, before opening a pull request, please [create an issue](https://github.com/btcpayserver/btcpayserver/issues/new/choose) or join [our community chat](https://chat.btcpayserver.org/) to get early feedback, discuss best ways to tackle the problem and to ensure there is no work duplication. -- [Setting up development environment on Windows](https://www.youtube.com/watch?v=ZePbMPSIvHM) -- [Setting up development environment Linux (Ubuntu)](https://www.youtube.com/watch?v=j486T_Rk-yw&t) -- [Setting up development environment MacOS](https://www.youtube.com/watch?v=GWR_CcMsEV0) +* [Setting up development environment on Windows](https://www.youtube.com/watch?v=ZePbMPSIvHM) +* [Setting up development environment Linux (Ubuntu)](https://www.youtube.com/watch?v=j486T_Rk-yw&t) +* [Setting up development environment MacOS](https://www.youtube.com/watch?v=GWR_CcMsEV0) -You also have an awesome video of our contributors which explains how to get started.[![Rockstar Dev and Britt Kelly - Btc Pay Server Code Along](https://img.youtube.com/vi/ZePbMPSIvHM/sddefault.jpg)](https://www.youtube.com/embed/VNMnd-dX9Q8) +You also have an awesome video of our contributors which explains how to get started. +[![Rockstar Dev and Britt Kelly - BTCPay Server Code Along](https://img.youtube.com/vi/ZePbMPSIvHM/sddefault.jpg)](https://www.youtube.com/embed/VNMnd-dX9Q8) -Here is some info about [how to extend the themes](https://docs.btcpayserver.org/Theme/) +Here is some info about [how to extend the themes](https://docs.btcpayserver.org/Theme/). ## How to build @@ -94,12 +95,14 @@ While the documentation advises to use docker-compose, you may want to build BTC First install .NET Core SDK v3.1 as specified by [Microsoft website](https://dotnet.microsoft.com/download/dotnet-core/3.1). On Powershell: -``` + +```powershell .\build.ps1 ``` On linux: -``` + +```sh ./build.sh ``` @@ -108,12 +111,14 @@ On linux: Use the `run` scripts to run BTCPayServer, this example shows how to print the available command line arguments of BTCPayServer. On Powershell: -``` + +```powershell .\run.ps1 --help ``` On linux: -``` + +```sh ./run.sh --help ``` @@ -121,7 +126,7 @@ On linux: If you want to debug, use Visual Studio Code or Visual Studio 2019. -You need to run the development time docker-compose as described [in the test guide](BTCPayServer.Tests/README.md). +You need to run the development time docker-compose as described [in the test guide](./BTCPayServer.Tests/README.md). You can then run the debugger by using the Launch Profile `Docker-Regtest` on either Visual Studio Code or Visual Studio 2017. @@ -136,7 +141,8 @@ Then use the `Docker-Regtest-https` debug profile. ## Other dependencies -For more information, see the documentation: [How to deploy a BTCPay server instance](https://github.com/btcpayserver/btcpayserver-doc/#deployment). +For more information, see the documentation: +[How to deploy a BTCPay server instance](https://docs.btcpayserver.org/Deployment/). ## Supported altcoins From 79f0e5768b748290e29fc8dea52829447d924fbd Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Thu, 23 Jul 2020 09:46:14 +0200 Subject: [PATCH 04/65] README: Use two rows for supporters --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 326af7c3c..95ac78fb7 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,8 @@ The BTCPay Server Project is proudly supported by these entities through the [BT DG Lab + +
StoreNameApp type + + Store @if (ViewData["StoreSortOrder"] != null) + { + + } + + + + Name @if (ViewData["NameSortOrder"] != null) + { + + } + + + + App Type @if (ViewData["AppTypeSortOrder"] != null) + { + + } + + Actions
- Store @if (ViewData["StoreSortOrder"] != null) + Store @if (ViewData["StoreNameSortOrder"] != null) { - + } - Name @if (ViewData["NameSortOrder"] != null) + Name @if (ViewData["AppNameSortOrder"] != null) { - + }
OKCoin From 6245684801507af9a8ec3f99fb5a4a728a78a627 Mon Sep 17 00:00:00 2001 From: Dennis Reimann Date: Thu, 23 Jul 2020 17:15:08 +0200 Subject: [PATCH 05/65] Improve Pull Payment view --- .../Views/PullPayment/ViewPullPayment.cshtml | 270 ++++++++---------- 1 file changed, 126 insertions(+), 144 deletions(-) diff --git a/BTCPayServer/Views/PullPayment/ViewPullPayment.cshtml b/BTCPayServer/Views/PullPayment/ViewPullPayment.cshtml index 0ee6f6c85..5b66ffb23 100644 --- a/BTCPayServer/Views/PullPayment/ViewPullPayment.cshtml +++ b/BTCPayServer/Views/PullPayment/ViewPullPayment.cshtml @@ -1,4 +1,5 @@ -@model BTCPayServer.Models.ViewPullPaymentModel +@using NUglify.Helpers +@model BTCPayServer.Models.ViewPullPaymentModel @addTagHelper *, BundlerMinifier.TagHelpers @inject BTCPayServer.HostedServices.CssThemeManager themeManager @@ -10,7 +11,7 @@ - @Model.Title + @ViewData["Title"] @@ -27,164 +28,145 @@ @Safe.Raw(Model.EmbeddedCSS) -
- @if (TempData.HasStatusMessage()) - { -
-
- -
-
- } - @if (!this.ViewContext.ModelState.IsValid) - { -
-
- @Html.ValidationSummary(string.Empty, new { @class = "alert alert-danger" }) -
-
- } -
-
-
+
+ +
+
+ @if (TempData.HasStatusMessage()) + { + + } + @if (!this.ViewContext.ModelState.IsValid) + { + @Html.ValidationSummary(string.Empty, new { @class = "alert alert-danger pb-0 text-center" }) + } + +
+ @if (!Model.Title.IsNullOrWhiteSpace()) + {

@Model.Title @Model.Status

- @if (Model.IsPending) - { -
-
-
- -
-
- -
- @Model.Currency.ToUpper() + } + @if (Model.IsPending) + { +
+ +
+
+ +
+
+
+ +
+ @Model.Currency.ToUpper() +
+
+
+
+
-
-
-
- } -
-
-
-
- - - - - - - - - - - - - - - - - - - - - @if (Model.ResetIn != String.Empty) - { - - - - - } - -
Pull payment details
Claim limit:@Model.AmountFormatted
Already claimed:@Model.AmountCollectedFormatted
Available claim:@Model.AmountDueFormatted
Reset in:@Model.ResetIn
- @if (Model.Description != null && Model.Description != "" && Model.Description != "
") - { -
@Safe.Raw(Model.Description)
- } -
-
-
-
- - - - - - - - - @if (Model.Payouts == null && !Model.Payouts.Any()) - { - - - - } - else - { - foreach (var invoice in Model.Payouts) - { - - - - - - - - - - - - - @if (!String.IsNullOrEmpty(invoice.Link)) - { - - - - - } - - - - - } - } - -
Awaiting claims
No claim made yet
Status@invoice.Status
Amount claimed@invoice.AmountFormatted
Destination@invoice.Destination
Transaction@invoice.TransactionId
-
-
+ } +
+
+ From b40dd468714341aa16e9e9a91f9f3301eac0ee10 Mon Sep 17 00:00:00 2001 From: "M.K. Safi" Date: Fri, 24 Jul 2020 10:13:34 -0700 Subject: [PATCH 06/65] Check-in VS Code debug config files --- .gitignore | 2 +- .vscode/launch.json | 36 ++++++++++++++++++++++++++++++++++++ .vscode/tasks.json | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.gitignore b/.gitignore index fbf55eb42..92d083db1 100644 --- a/.gitignore +++ b/.gitignore @@ -292,5 +292,5 @@ __pycache__/ BTCPayServer/wwwroot/bundles/* !BTCPayServer/wwwroot/bundles/.gitignore -.vscode +.vscode/settings.json BTCPayServer/testpwd diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..b9cbedc8a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,36 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (web)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/BTCPayServer/bin/Debug/netcoreapp3.1/BTCPayServer.dll", + "args": [], + "cwd": "${workspaceFolder}/BTCPayServer", + "stopAtEntry": false, + // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser + "serverReadyAction": { + "action": "openExternally", + "pattern": "\\bNow listening on:\\s+(https?://\\S+)" + }, + "env": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "sourceFileMap": { + "/Views": "${workspaceFolder}/Views" + } + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..1f89fbf45 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,42 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/BTCPayServer/BTCPayServer.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/BTCPayServer/BTCPayServer.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "${workspaceFolder}/BTCPayServer/BTCPayServer.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file From 272de60f9f41b2c4888662cc4819e75e2e73027e Mon Sep 17 00:00:00 2001 From: "M.K. Safi" Date: Fri, 24 Jul 2020 10:15:31 -0700 Subject: [PATCH 07/65] Edit `.gitignore` --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 92d083db1..c5b4fa063 100644 --- a/.gitignore +++ b/.gitignore @@ -292,5 +292,7 @@ __pycache__/ BTCPayServer/wwwroot/bundles/* !BTCPayServer/wwwroot/bundles/.gitignore -.vscode/settings.json +.vscode +!.vscode/launch.json +!.vscode/tasks.json BTCPayServer/testpwd From 22f22c0fa0176abf3872d500c1946513397b9807 Mon Sep 17 00:00:00 2001 From: "M.K. Safi" Date: Fri, 24 Jul 2020 12:53:36 -0700 Subject: [PATCH 08/65] Set `logging.moduleLoad` to `false` --- .vscode/launch.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.vscode/launch.json b/.vscode/launch.json index b9cbedc8a..626ec3a90 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -24,6 +24,9 @@ }, "sourceFileMap": { "/Views": "${workspaceFolder}/Views" + }, + "logging": { + "moduleLoad": false } }, { From df1447b91722938a5d7b991f3823b93f5f80bae9 Mon Sep 17 00:00:00 2001 From: Umar Bolatov Date: Fri, 24 Jul 2020 21:33:02 -0700 Subject: [PATCH 09/65] Add pagination to wallet transactions page close #1771 --- BTCPayServer/Controllers/WalletsController.cs | 16 ++++- .../ListTransactionsViewModel.cs | 3 + .../Views/Wallets/WalletTransactions.cshtml | 67 +++++++++++++++++++ 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/BTCPayServer/Controllers/WalletsController.cs b/BTCPayServer/Controllers/WalletsController.cs index 79a21734f..5d73f04c4 100644 --- a/BTCPayServer/Controllers/WalletsController.cs +++ b/BTCPayServer/Controllers/WalletsController.cs @@ -259,7 +259,11 @@ namespace BTCPayServer.Controllers [Route("{walletId}/transactions")] public async Task WalletTransactions( [ModelBinder(typeof(WalletIdModelBinder))] - WalletId walletId, string labelFilter = null) + WalletId walletId, + string labelFilter = null, + int skip = 0, + int count = 50 + ) { DerivationSchemeSettings paymentMethod = GetDerivationSchemeSettings(walletId); if (paymentMethod == null) @@ -271,7 +275,12 @@ namespace BTCPayServer.Controllers var transactions = await wallet.FetchTransactions(paymentMethod.AccountDerivation); var walletBlob = await walletBlobAsync; var walletTransactionsInfo = await walletTransactionsInfoAsync; - var model = new ListTransactionsViewModel(); + var model = new ListTransactionsViewModel + { + Skip = skip, + Count = count, + Total = 0 + }; if (transactions == null) { TempData.SetStatusMessageModel(new StatusMessageModel() @@ -309,7 +318,8 @@ namespace BTCPayServer.Controllers model.Transactions.Add(vm); } - model.Transactions = model.Transactions.OrderByDescending(t => t.Timestamp).ToList(); + model.Total = model.Transactions.Count; + model.Transactions = model.Transactions.OrderByDescending(t => t.Timestamp).Skip(skip).Take(count).ToList(); } return View(model); diff --git a/BTCPayServer/Models/WalletViewModels/ListTransactionsViewModel.cs b/BTCPayServer/Models/WalletViewModels/ListTransactionsViewModel.cs index d14788c0a..d63640ddd 100644 --- a/BTCPayServer/Models/WalletViewModels/ListTransactionsViewModel.cs +++ b/BTCPayServer/Models/WalletViewModels/ListTransactionsViewModel.cs @@ -19,5 +19,8 @@ namespace BTCPayServer.Models.WalletViewModels } public HashSet
+ + @{ + string ListTransactionsPage(int prevNext, int count) + { + var skip = Model.Skip; + if (prevNext == -1) + { + skip = Math.Max(0, Model.Skip - Model.Count); + } + else if (prevNext == 1) + { + skip = Model.Skip + count; + } + + var act = Url.Action("WalletTransactions", new + { + labelFilter = Context.Request.Query["labelFilter"], + skip = skip, + count = count, + }); + + return act; + } + } From 97b7d920cb230ab615cb0f50fe63b68496826a23 Mon Sep 17 00:00:00 2001 From: "M.K. Safi" Date: Sat, 25 Jul 2020 10:04:33 -0700 Subject: [PATCH 10/65] Check-in `.vscode/extensions.json` --- .gitignore | 3 ++- .vscode/extensions.json | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .vscode/extensions.json diff --git a/.gitignore b/.gitignore index c5b4fa063..5957b2905 100644 --- a/.gitignore +++ b/.gitignore @@ -292,7 +292,8 @@ __pycache__/ BTCPayServer/wwwroot/bundles/* !BTCPayServer/wwwroot/bundles/.gitignore -.vscode +.vscode/* !.vscode/launch.json !.vscode/tasks.json +!.vscode/extensions.json BTCPayServer/testpwd diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..b6962761f --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-dotnettools.csharp"] +} From 1f3f456123af020fb68cae6d62fd1973585dc46b Mon Sep 17 00:00:00 2001 From: "M.K. Safi" Date: Sat, 25 Jul 2020 10:07:47 -0700 Subject: [PATCH 11/65] Fix JSON indentations --- .vscode/launch.json | 12 ++++++------ .vscode/tasks.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 626ec3a90..1e6f2371c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,9 +1,9 @@ { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "version": "0.2.0", - "configurations": [ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ { "name": ".NET Core Launch (web)", "type": "coreclr", @@ -36,4 +36,4 @@ "processId": "${command:pickProcess}" } ] -} \ No newline at end of file +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 1f89fbf45..0c09b3f3a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -39,4 +39,4 @@ "problemMatcher": "$msCompile" } ] -} \ No newline at end of file +} From 60157eb70cff47232f2c28c22a0bbf1b86ba7b20 Mon Sep 17 00:00:00 2001 From: "M.K. Safi" Date: Sat, 25 Jul 2020 10:11:30 -0700 Subject: [PATCH 12/65] Remove .NET Core Attach debug configurations --- .vscode/launch.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 1e6f2371c..83182cff2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -28,12 +28,6 @@ "logging": { "moduleLoad": false } - }, - { - "name": ".NET Core Attach", - "type": "coreclr", - "request": "attach", - "processId": "${command:pickProcess}" } ] } From 810e12f474e1984ad093457cb5be85b7f2b888a0 Mon Sep 17 00:00:00 2001 From: Esky33 Date: Sun, 26 Jul 2020 00:30:34 +0100 Subject: [PATCH 13/65] Update .gitignore all the .DS_Store files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .gitignore all the .DS_Store files in every folder and subfolder - improves UX If you are using macOS, visual studio, visual code, rider, your system appends the .DS_Store file in your directories. It’s not a big issue, but often you need to exclude these files explicitly in your .gitignore file, to prevent any unnecessary files in your commit. notice for btcpay Mac dev users.. This will never allow the .DS_Store file to sneak in your git. But, if it's already there, you can write in your project terminal: find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch then commit and push the changes to remove the .DS_Store from your remote repo: git commit -m "Remove .DS_Store from everywhere" git push origin master --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fbf55eb42..d6a175f4e 100644 --- a/.gitignore +++ b/.gitignore @@ -294,3 +294,4 @@ BTCPayServer/wwwroot/bundles/* .vscode BTCPayServer/testpwd +.DS_Store From e03311e5ec7c9434fb8c6be7372591d2094e96b1 Mon Sep 17 00:00:00 2001 From: Umar Bolatov Date: Sat, 25 Jul 2020 14:37:30 -0700 Subject: [PATCH 14/65] Add margin to "Delete this store" button fix #1770 --- BTCPayServer/Views/Stores/UpdateStore.cshtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BTCPayServer/Views/Stores/UpdateStore.cshtml b/BTCPayServer/Views/Stores/UpdateStore.cshtml index 9c8c375a1..1fd5b092d 100644 --- a/BTCPayServer/Views/Stores/UpdateStore.cshtml +++ b/BTCPayServer/Views/Stores/UpdateStore.cshtml @@ -281,7 +281,7 @@

Other actions

Click here to see more actions

} From ba316d02ca477aeba4bfc7aad8d93dd824a6c19b Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Mon, 27 Jul 2020 13:27:47 +0900 Subject: [PATCH 15/65] Improve query performance for invoice listing --- BTCPayServer/Extensions.cs | 17 +++++++++++++++++ .../Services/Invoices/InvoiceRepository.cs | 11 +++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/BTCPayServer/Extensions.cs b/BTCPayServer/Extensions.cs index 52f4b54d5..eb4ad0f44 100644 --- a/BTCPayServer/Extensions.cs +++ b/BTCPayServer/Extensions.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Net; using System.Net.WebSockets; +using System.Reflection; using System.Security.Claims; using System.Text; using System.Threading; @@ -449,5 +450,21 @@ namespace BTCPayServer }; return controller.View("PostRedirect", redirectVm); } + + public static string ToSql(this IQueryable query) where TEntity : class + { + var enumerator = query.Provider.Execute>(query.Expression).GetEnumerator(); + var relationalCommandCache = enumerator.Private("_relationalCommandCache"); + var selectExpression = relationalCommandCache.Private("_selectExpression"); + var factory = relationalCommandCache.Private("_querySqlGeneratorFactory"); + + var sqlGenerator = factory.Create(); + var command = sqlGenerator.GetCommand(selectExpression); + + string sql = command.CommandText; + return sql; + } + private static object Private(this object obj, string privateField) => obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj); + private static T Private(this object obj, string privateField) => (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj); } } diff --git a/BTCPayServer/Services/Invoices/InvoiceRepository.cs b/BTCPayServer/Services/Invoices/InvoiceRepository.cs index 042d46644..32b81f693 100644 --- a/BTCPayServer/Services/Invoices/InvoiceRepository.cs +++ b/BTCPayServer/Services/Invoices/InvoiceRepository.cs @@ -527,7 +527,9 @@ retry: private IQueryable GetInvoiceQuery(ApplicationDbContext context, InvoiceQuery queryObject) { - IQueryable query = context.Invoices; + IQueryable query = queryObject.UserId is null + ? context.Invoices + : context.UserStore.Where(u => u.ApplicationUserId == queryObject.UserId).SelectMany(c => c.StoreData.Invoices); if (!queryObject.IncludeArchived) { @@ -546,11 +548,6 @@ retry: query = query.Where(i => stores.Contains(i.StoreDataId)); } - if (queryObject.UserId != null) - { - query = query.Where(i => i.StoreData.UserStores.Any(u => u.ApplicationUserId == queryObject.UserId)); - } - if (!string.IsNullOrEmpty(queryObject.TextSearch)) { var ids = new HashSet(SearchInvoice(queryObject.TextSearch)).ToArray(); @@ -605,7 +602,6 @@ retry: if (queryObject.Count != null) query = query.Take(queryObject.Count.Value); - return query; } @@ -628,7 +624,6 @@ retry: query = query.Include(o => o.HistoricalAddressInvoices).Include(o => o.AddressInvoices); if (queryObject.IncludeEvents) query = query.Include(o => o.Events); - var data = await query.ToArrayAsync().ConfigureAwait(false); return data.Select(ToEntity).ToArray(); } From 6bacddc159bac3aaa6043d5019e3d2b042ddca40 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sun, 19 Jul 2020 16:20:28 -0500 Subject: [PATCH 16/65] Refactoring ListInvoicePreferences --- .../Controllers/InvoiceController.UI.cs | 24 +++++++------------ .../Logic/ListInvoicesPreference.cs | 24 +++++++++++++++++++ 2 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 BTCPayServer/Controllers/Logic/ListInvoicesPreference.cs diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index 572cc248a..b438405ab 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using BTCPayServer.Client; using BTCPayServer.Client.Models; +using BTCPayServer.Controllers.Logic; using BTCPayServer.Data; using BTCPayServer.Events; using BTCPayServer.Filters; @@ -598,17 +599,11 @@ namespace BTCPayServer.Controllers return Ok("{}"); } - public class InvoicePreference - { - public int? TimezoneOffset { get; set; } - public string SearchTerm { get; set; } - } - [HttpGet] [Route("invoices")] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [BitpayAPIConstraint(false)] - public async Task ListInvoices(string searchTerm = null, int skip = 0, int count = 50, int? timezoneOffset = null) + public async Task ListInvoices(string searchTerm = null, int skip = 0, int count = 50, int timezoneOffset = 0) { // If the user enter an empty searchTerm, then the variable will be null and not empty string // but we want searchTerm to be null only if the user is browsing the page via some link @@ -618,20 +613,19 @@ namespace BTCPayServer.Controllers null; if (searchTerm is null) { - if (this.Request.Cookies.TryGetValue("ListInvoicePreferences", out var str)) + if (this.Request.Cookies.TryGetValue(ListInvoicesPreference.KEY, out var str)) { - var preferences = JsonConvert.DeserializeObject(str); + var preferences = JsonConvert.DeserializeObject(str); searchTerm = preferences.SearchTerm; - timezoneOffset = timezoneOffset is int v ? v : preferences.TimezoneOffset; + timezoneOffset = preferences.TimezoneOffset ?? 0; } } else { - var preferences = new InvoicePreference(); - preferences.SearchTerm = searchTerm; - preferences.TimezoneOffset = timezoneOffset; - this.Response.Cookies.Append("ListInvoicePreferences", JsonConvert.SerializeObject(preferences)); + this.Response.Cookies.Append(ListInvoicesPreference.KEY, + JsonConvert.SerializeObject(new ListInvoicesPreference(searchTerm, timezoneOffset))); } + var fs = new SearchString(searchTerm); var storeIds = fs.GetFilterArray("storeid") != null ? fs.GetFilterArray("storeid") : new List().ToArray(); @@ -643,7 +637,7 @@ namespace BTCPayServer.Controllers StoreIds = storeIds, TimezoneOffset = timezoneOffset }; - InvoiceQuery invoiceQuery = GetInvoiceQuery(searchTerm, timezoneOffset ?? 0); + InvoiceQuery invoiceQuery = GetInvoiceQuery(searchTerm, timezoneOffset); var counting = _InvoiceRepository.GetInvoicesTotal(invoiceQuery); invoiceQuery.Count = count; invoiceQuery.Skip = skip; diff --git a/BTCPayServer/Controllers/Logic/ListInvoicesPreference.cs b/BTCPayServer/Controllers/Logic/ListInvoicesPreference.cs new file mode 100644 index 000000000..620cc1182 --- /dev/null +++ b/BTCPayServer/Controllers/Logic/ListInvoicesPreference.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BTCPayServer.Controllers.Logic +{ + public class ListInvoicesPreference + { + public const string KEY = "ListInvoicePreferences"; + public ListInvoicesPreference() { } + + public ListInvoicesPreference(string searchTerm, int timezoneOffset) + { + SearchTerm = searchTerm; + if (timezoneOffset != 0) + TimezoneOffset = timezoneOffset; + } + + public int? TimezoneOffset { get; set; } + public string SearchTerm { get; set; } + } +} From 9d9d0461ad21e05325c48f6c1c4a9ec62832d458 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sun, 19 Jul 2020 16:40:57 -0500 Subject: [PATCH 17/65] Generalizing saving of search, applying it to PaymentRequests grid --- BTCPayServer.Tests/UnitTest1.cs | 2 +- .../Controllers/InvoiceController.UI.cs | 25 ++-------- .../Controllers/Logic/ListCookiePreference.cs | 50 +++++++++++++++++++ .../Logic/ListInvoicesPreference.cs | 24 --------- .../Controllers/PaymentRequestController.cs | 6 ++- .../PaymentRequest/GetPaymentRequests.cshtml | 2 +- 6 files changed, 60 insertions(+), 49 deletions(-) create mode 100644 BTCPayServer/Controllers/Logic/ListCookiePreference.cs delete mode 100644 BTCPayServer/Controllers/Logic/ListInvoicesPreference.cs diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 6be6bdc52..7ff50622a 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -1354,7 +1354,7 @@ namespace BTCPayServer.Tests { var result = (Models.InvoicingModels.InvoicesModel)((ViewResult)acc.GetController() - .ListInvoices(filter).Result).Model; + .ListInvoices(searchTerm:filter).Result).Model; Assert.Equal(expected, result.Invoices.Any(i => i.InvoiceId == invoiceId)); } diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index b438405ab..69db96a19 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -603,28 +603,9 @@ namespace BTCPayServer.Controllers [Route("invoices")] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [BitpayAPIConstraint(false)] - public async Task ListInvoices(string searchTerm = null, int skip = 0, int count = 50, int timezoneOffset = 0) + public async Task ListInvoices(int skip = 0, int count = 50, string searchTerm = null, int? timezoneOffset = null) { - // If the user enter an empty searchTerm, then the variable will be null and not empty string - // but we want searchTerm to be null only if the user is browsing the page via some link - // NOT if the user entered some empty search - searchTerm = searchTerm is string ? searchTerm : - this.Request.Query.ContainsKey(nameof(searchTerm)) ? string.Empty : - null; - if (searchTerm is null) - { - if (this.Request.Cookies.TryGetValue(ListInvoicesPreference.KEY, out var str)) - { - var preferences = JsonConvert.DeserializeObject(str); - searchTerm = preferences.SearchTerm; - timezoneOffset = preferences.TimezoneOffset ?? 0; - } - } - else - { - this.Response.Cookies.Append(ListInvoicesPreference.KEY, - JsonConvert.SerializeObject(new ListInvoicesPreference(searchTerm, timezoneOffset))); - } + ListCookiePreference.Parse(this, "ListInvoicesPreference", ref searchTerm, ref timezoneOffset); var fs = new SearchString(searchTerm); var storeIds = fs.GetFilterArray("storeid") != null ? fs.GetFilterArray("storeid") : new List().ToArray(); @@ -637,7 +618,7 @@ namespace BTCPayServer.Controllers StoreIds = storeIds, TimezoneOffset = timezoneOffset }; - InvoiceQuery invoiceQuery = GetInvoiceQuery(searchTerm, timezoneOffset); + InvoiceQuery invoiceQuery = GetInvoiceQuery(searchTerm, timezoneOffset ?? 0); var counting = _InvoiceRepository.GetInvoicesTotal(invoiceQuery); invoiceQuery.Count = count; invoiceQuery.Skip = skip; diff --git a/BTCPayServer/Controllers/Logic/ListCookiePreference.cs b/BTCPayServer/Controllers/Logic/ListCookiePreference.cs new file mode 100644 index 000000000..ab3ccac4b --- /dev/null +++ b/BTCPayServer/Controllers/Logic/ListCookiePreference.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; + +namespace BTCPayServer.Controllers.Logic +{ + public class ListCookiePreference + { + public ListCookiePreference() { } + + public ListCookiePreference(string searchTerm, int? timezoneOffset) + { + SearchTerm = searchTerm; + TimezoneOffset = timezoneOffset; + } + + public int? TimezoneOffset { get; set; } + public string SearchTerm { get; set; } + + + public static void Parse(ControllerBase ctrl, string key, + ref string searchTerm, ref int? timezoneOffset) + { + // If the user enter an empty searchTerm, then the variable will be null and not empty string + // but we want searchTerm to be null only if the user is browsing the page via some link + // NOT if the user entered some empty search + searchTerm = searchTerm is string ? searchTerm : + ctrl.Request.Query.ContainsKey(nameof(searchTerm)) ? string.Empty : + null; + if (searchTerm is null) + { + if (ctrl.Request.Cookies.TryGetValue(key, out var str)) + { + var preferences = JsonConvert.DeserializeObject(str); + searchTerm = preferences.SearchTerm; + timezoneOffset = preferences.TimezoneOffset ?? 0; + } + } + else + { + ctrl.Response.Cookies.Append(key, + JsonConvert.SerializeObject(new ListCookiePreference(searchTerm, timezoneOffset))); + } + } + } +} diff --git a/BTCPayServer/Controllers/Logic/ListInvoicesPreference.cs b/BTCPayServer/Controllers/Logic/ListInvoicesPreference.cs deleted file mode 100644 index 620cc1182..000000000 --- a/BTCPayServer/Controllers/Logic/ListInvoicesPreference.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BTCPayServer.Controllers.Logic -{ - public class ListInvoicesPreference - { - public const string KEY = "ListInvoicePreferences"; - public ListInvoicesPreference() { } - - public ListInvoicesPreference(string searchTerm, int timezoneOffset) - { - SearchTerm = searchTerm; - if (timezoneOffset != 0) - TimezoneOffset = timezoneOffset; - } - - public int? TimezoneOffset { get; set; } - public string SearchTerm { get; set; } - } -} diff --git a/BTCPayServer/Controllers/PaymentRequestController.cs b/BTCPayServer/Controllers/PaymentRequestController.cs index 077d567c1..4488285ec 100644 --- a/BTCPayServer/Controllers/PaymentRequestController.cs +++ b/BTCPayServer/Controllers/PaymentRequestController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using BTCPayServer.Controllers.Logic; using BTCPayServer.Data; using BTCPayServer.Events; using BTCPayServer.Filters; @@ -61,8 +62,11 @@ namespace BTCPayServer.Controllers [HttpGet] [Route("")] [BitpayAPIConstraint(false)] - public async Task GetPaymentRequests(int skip = 0, int count = 50, bool includeArchived = false) + public async Task GetPaymentRequests(int skip = 0, int count = 50, string searchTerm = null, int? timezoneOffset = null) { + ListCookiePreference.Parse(this, "ListPaymentRequestsPreference", ref searchTerm, ref timezoneOffset); + + var includeArchived = new SearchString(searchTerm).GetFilterBool("includearchived") == true; var result = await _PaymentRequestRepository.FindPaymentRequests(new PaymentRequestQuery() { UserId = GetUserId(), diff --git a/BTCPayServer/Views/PaymentRequest/GetPaymentRequests.cshtml b/BTCPayServer/Views/PaymentRequest/GetPaymentRequests.cshtml index c189d5fee..3c172550d 100644 --- a/BTCPayServer/Views/PaymentRequest/GetPaymentRequests.cshtml +++ b/BTCPayServer/Views/PaymentRequest/GetPaymentRequests.cshtml @@ -99,7 +99,7 @@ { skip = Model.Skip, count = Model.Count, - includeArchived = !Model.IncludeArchived + searchTerm = "includearchived:"+ !Model.IncludeArchived })"> @if (Model.IncludeArchived) { From e3a8e1a187ab081c6378fc082c1b8a630c04d5d2 Mon Sep 17 00:00:00 2001 From: rockstardev Date: Sun, 19 Jul 2020 16:49:13 -0500 Subject: [PATCH 18/65] Applying conventions from ListInvoice on PaymentRequests --- .../Controllers/PaymentRequestController.cs | 3 +- .../ListPaymentRequestsViewModel.cs | 6 +- .../PaymentRequest/GetPaymentRequests.cshtml | 103 ++++++++++-------- 3 files changed, 61 insertions(+), 51 deletions(-) diff --git a/BTCPayServer/Controllers/PaymentRequestController.cs b/BTCPayServer/Controllers/PaymentRequestController.cs index 4488285ec..ab887f7eb 100644 --- a/BTCPayServer/Controllers/PaymentRequestController.cs +++ b/BTCPayServer/Controllers/PaymentRequestController.cs @@ -76,10 +76,11 @@ namespace BTCPayServer.Controllers }); return View(new ListPaymentRequestsViewModel() { - IncludeArchived = includeArchived, Skip = skip, Count = count, Total = result.Total, + SearchTerm = searchTerm, + TimezoneOffset = timezoneOffset, Items = result.Items.Select(data => new ViewPaymentRequestViewModel(data)).ToList() }); } diff --git a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs index 0abe7c75c..8f9cedc70 100644 --- a/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs +++ b/BTCPayServer/Models/PaymentRequestViewModels/ListPaymentRequestsViewModel.cs @@ -12,11 +12,11 @@ namespace BTCPayServer.Models.PaymentRequestViewModels { public int Skip { get; set; } public int Count { get; set; } - + public int Total { get; set; } + public string SearchTerm { get; set; } + public int? TimezoneOffset { get; set; } public List Items { get; set; } - public int Total { get; set; } - public bool IncludeArchived { get; set; } } public class UpdatePaymentRequestViewModel diff --git a/BTCPayServer/Views/PaymentRequest/GetPaymentRequests.cshtml b/BTCPayServer/Views/PaymentRequest/GetPaymentRequests.cshtml index 3c172550d..b14e96419 100644 --- a/BTCPayServer/Views/PaymentRequest/GetPaymentRequests.cshtml +++ b/BTCPayServer/Views/PaymentRequest/GetPaymentRequests.cshtml @@ -10,7 +10,7 @@ {
- +
} @@ -18,10 +18,35 @@

Payment Requests


+

Create, search or pay an payment request.

+ +
+ +
+ + +
+ + + + +
+
+ +
+