diff --git a/BTCPayServer.Abstractions/Contracts/ISwaggerProvider.cs b/BTCPayServer.Abstractions/Contracts/ISwaggerProvider.cs new file mode 100644 index 000000000..0e32786ba --- /dev/null +++ b/BTCPayServer.Abstractions/Contracts/ISwaggerProvider.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; + +namespace BTCPayServer.Abstractions.Contracts; + +public interface ISwaggerProvider +{ + Task Fetch(); +} diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 0966e9c90..fa18be504 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -142,7 +142,7 @@ namespace BTCPayServer.Tests var sresp = Assert .IsType(await tester.PayTester.GetController(acc.UserId, acc.StoreId) - .Swagger()).Value.ToJson(); + .Swagger(tester.PayTester.GetService>())).Value.ToJson(); JObject swagger = JObject.Parse(sresp); var schema = JSchema.Parse(File.ReadAllText(TestUtils.GetTestDataFullPath("OpenAPI-Specification-schema.json"))); IList errors; @@ -191,7 +191,7 @@ namespace BTCPayServer.Tests var sresp = Assert .IsType(await tester.PayTester.GetController(acc.UserId, acc.StoreId) - .Swagger()).Value.ToJson(); + .Swagger(tester.PayTester.GetService>())).Value.ToJson(); JObject json = JObject.Parse(sresp); diff --git a/BTCPayServer/Controllers/UIHomeController.cs b/BTCPayServer/Controllers/UIHomeController.cs index 1a8c488f5..afc7e5e3d 100644 --- a/BTCPayServer/Controllers/UIHomeController.cs +++ b/BTCPayServer/Controllers/UIHomeController.cs @@ -41,7 +41,6 @@ namespace BTCPayServer.Controllers { private readonly ISettingsRepository _settingsRepository; private readonly StoreRepository _storeRepository; - private readonly IFileProvider _fileProvider; private readonly BTCPayNetworkProvider _networkProvider; private IHttpClientFactory HttpClientFactory { get; } private SignInManager SignInManager { get; } @@ -49,7 +48,6 @@ namespace BTCPayServer.Controllers public UIHomeController(IHttpClientFactory httpClientFactory, ISettingsRepository settingsRepository, - IWebHostEnvironment webHostEnvironment, LanguageService languageService, StoreRepository storeRepository, BTCPayNetworkProvider networkProvider, @@ -60,7 +58,6 @@ namespace BTCPayServer.Controllers LanguageService = languageService; _networkProvider = networkProvider; _storeRepository = storeRepository; - _fileProvider = webHostEnvironment.WebRootFileProvider; SignInManager = signInManager; } @@ -127,22 +124,19 @@ namespace BTCPayServer.Controllers [Route("swagger/v1/swagger.json")] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie + "," + AuthenticationSchemes.Greenfield)] - public async Task Swagger() + public async Task Swagger([FromServices] IEnumerable swaggerProviders) { - JObject json = new JObject(); - var directoryContents = _fileProvider.GetDirectoryContents("swagger/v1"); - foreach (IFileInfo fi in directoryContents) + JObject json = new(); + var res = await Task.WhenAll(swaggerProviders.Select(provider => provider.Fetch())); + foreach (JObject jObject in res) { - await using var stream = fi.CreateReadStream(); - using var reader = new StreamReader(fi.CreateReadStream()); - json.Merge(JObject.Parse(await reader.ReadToEndAsync())); + json.Merge(jObject); } var servers = new JArray(); servers.Add(new JObject(new JProperty("url", HttpContext.Request.GetAbsoluteRoot()))); json["servers"] = servers; return Json(json); } - [Route("docs")] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] public IActionResult SwaggerDocs() diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index a9a4fe090..1d2f68b27 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -99,6 +99,7 @@ namespace BTCPayServer.Hosting services.TryAddSingleton(); services.TryAddSingleton(); services.AddSingleton(provider => provider.GetRequiredService()); + services.AddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); services.TryAddSingleton(); diff --git a/BTCPayServer/Services/DefaultSwaggerProvider.cs b/BTCPayServer/Services/DefaultSwaggerProvider.cs new file mode 100644 index 000000000..01b05d6d6 --- /dev/null +++ b/BTCPayServer/Services/DefaultSwaggerProvider.cs @@ -0,0 +1,33 @@ +using System.IO; +using System.Threading.Tasks; +using BTCPayServer.Abstractions.Contracts; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.FileProviders; +using Newtonsoft.Json.Linq; + +namespace BTCPayServer.Services; + +public class DefaultSwaggerProvider: ISwaggerProvider +{ + private readonly IFileProvider _fileProvider; + + public DefaultSwaggerProvider(IWebHostEnvironment webHostEnvironment) + { + + _fileProvider = webHostEnvironment.WebRootFileProvider; + } + public async Task Fetch() + { + + JObject json = new JObject(); + var directoryContents = _fileProvider.GetDirectoryContents("swagger/v1"); + foreach (IFileInfo fi in directoryContents) + { + await using var stream = fi.CreateReadStream(); + using var reader = new StreamReader(fi.CreateReadStream()); + json.Merge(JObject.Parse(await reader.ReadToEndAsync())); + } + + return json; + } +} diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.json index 6dab9f18d..552b463eb 100644 --- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.json +++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.json @@ -76,7 +76,7 @@ "securitySchemes": { "API_Key": { "type": "apiKey", - "description": "BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n* `unrestricted`: Unrestricted access\n* `btcpay.user.candeleteuser`: Delete user\n* `btcpay.user.canviewprofile`: View your profile\n* `btcpay.user.canmodifyprofile`: Manage your profile\n* `btcpay.user.canmanagenotificationsforuser`: Manage your notifications\n* `btcpay.user.canviewnotificationsforuser`: View your notifications\n\nThe following permissions are available if the user is an administrator:\n\n* `btcpay.server.canviewusers`: View users\n* `btcpay.server.cancreateuser`: Create new users\n* `btcpay.server.canmodifyserversettings`: Manage your server\n* `btcpay.server.canuseinternallightningnode`: Use the internal lightning node\n* `btcpay.server.cancreatelightninginvoiceinternalnode`: Create invoices with internal lightning node\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n* `btcpay.store.canmodifystoresettings`: Modify your stores\n* `btcpay.store.webhooks.canmodifywebhooks`: Modify stores webhooks\n* `btcpay.store.canviewstoresettings`: View your stores\n* `btcpay.store.cancreateinvoice`: Create an invoice\n* `btcpay.store.canviewinvoices`: View invoices\n* `btcpay.store.canmodifyinvoices`: Modify invoices\n* `btcpay.store.canmodifypaymentrequests`: Modify your payment requests\n* `btcpay.store.canviewpaymentrequests`: View your payment requests\n* `btcpay.store.canuselightningnode`: Use the lightning nodes associated with your stores\n* `btcpay.store.cancreatelightninginvoice`: Create invoices the lightning nodes associated with your stores\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n", + "description": "BTCPay Server supports authenticating and authorizing users through an API Key that is generated by them. Send the API Key as a header value to Authorization with the format: `token {token}`. For a smoother experience, you can generate a url that redirects users to an API key creation screen.\n\n The following permissions are available to the context of the user creating the API Key:\n\n* `unrestricted`: Unrestricted access\n* `btcpay.user.candeleteuser`: Delete user\n* `btcpay.user.canviewprofile`: View your profile\n* `btcpay.user.canmodifyprofile`: Manage your profile\n* `btcpay.user.canmanagenotificationsforuser`: Manage your notifications\n* `btcpay.user.canviewnotificationsforuser`: View your notifications\n\nThe following permissions are available if the user is an administrator:\n\n* `btcpay.server.canviewusers`: View users\n* `btcpay.server.cancreateuser`: Create new users\n* `btcpay.server.canmodifyserversettings`: Manage your server\n* `btcpay.server.canuseinternallightningnode`: Use the internal lightning node\n* `btcpay.server.cancreatelightninginvoiceinternalnode`: Create invoices with internal lightning node\n\nThe following permissions applies to all stores of the user, you can limit to a specific store with the following format: `btcpay.store.cancreateinvoice:6HSHAEU4iYWtjxtyRs9KyPjM9GAQp8kw2T9VWbGG1FnZ`:\n\n* `btcpay.store.canmodifystoresettings`: Modify your stores\n* `btcpay.store.webhooks.canmodifywebhooks`: Modify stores webhooks\n* `btcpay.store.canviewstoresettings`: View your stores\n* `btcpay.store.cancreateinvoice`: Create an invoice\n* `btcpay.store.canviewinvoices`: View invoices\n* `btcpay.store.canmodifyinvoices`: Modify invoices\n* `btcpay.store.canmodifypaymentrequests`: Modify your payment requests\n* `btcpay.store.canviewpaymentrequests`: View your payment requests\n* `btcpay.store.canmanagepullpayments`: Manage your pull payments\n* `btcpay.store.canuselightningnode`: Use the lightning nodes associated with your stores\n* `btcpay.store.cancreatelightninginvoice`: Create invoices the lightning nodes associated with your stores\n\nNote that API Keys only limits permission of a user and can never expand it. If an API Key has the permission `btcpay.server.canmodifyserversettings` but that the user account creating this API Key is not administrator, the API Key will not be able to modify the server settings.\nSome permissions may include other permissions, see [this operation](#operation/permissionsMetadata).\n", "name": "Authorization", "in": "header" },