Show tor services inside hidden directories in Server Settings/Services

This commit is contained in:
nicolas.dorier
2019-03-17 12:57:18 +09:00
parent 17b18d820f
commit 4769b1d452
7 changed files with 118 additions and 26 deletions

View File

@@ -149,6 +149,7 @@ namespace BTCPayServer.Configuration
PostgresConnectionString = conf.GetOrDefault<string>("postgres", null); PostgresConnectionString = conf.GetOrDefault<string>("postgres", null);
MySQLConnectionString = conf.GetOrDefault<string>("mysql", null); MySQLConnectionString = conf.GetOrDefault<string>("mysql", null);
BundleJsCss = conf.GetOrDefault<bool>("bundlejscss", true); BundleJsCss = conf.GetOrDefault<bool>("bundlejscss", true);
TorHiddenServicesDirectory = conf.GetOrDefault<string>("torservices", null);
var sshSettings = ParseSSHConfiguration(conf); var sshSettings = ParseSSHConfiguration(conf);
if ((!string.IsNullOrEmpty(sshSettings.Password) || !string.IsNullOrEmpty(sshSettings.KeyFile)) && !string.IsNullOrEmpty(sshSettings.Server)) if ((!string.IsNullOrEmpty(sshSettings.Password) || !string.IsNullOrEmpty(sshSettings.KeyFile)) && !string.IsNullOrEmpty(sshSettings.Server))
@@ -273,5 +274,6 @@ namespace BTCPayServer.Configuration
get; get;
set; set;
} }
public string TorHiddenServicesDirectory { get; set; }
} }
} }

View File

@@ -40,6 +40,7 @@ namespace BTCPayServer.Configuration
app.Option("--sshkeyfile", "SSH private key file to manage BTCPay (default: empty)", CommandOptionType.SingleValue); app.Option("--sshkeyfile", "SSH private key file to manage BTCPay (default: empty)", CommandOptionType.SingleValue);
app.Option("--sshkeyfilepassword", "Password of the SSH keyfile (default: empty)", CommandOptionType.SingleValue); app.Option("--sshkeyfilepassword", "Password of the SSH keyfile (default: empty)", CommandOptionType.SingleValue);
app.Option("--sshtrustedfingerprints", "SSH Host public key fingerprint or sha256 (default: empty, it will allow untrusted connections)", CommandOptionType.SingleValue); app.Option("--sshtrustedfingerprints", "SSH Host public key fingerprint or sha256 (default: empty, it will allow untrusted connections)", CommandOptionType.SingleValue);
app.Option("--torservices", "Path to folder containing hidden services directories (default: empty)", CommandOptionType.SingleValue);
app.Option("--debuglog", "A rolling log file for debug messages.", CommandOptionType.SingleValue); app.Option("--debuglog", "A rolling log file for debug messages.", CommandOptionType.SingleValue);
app.Option("--debugloglevel", "The severity you log (default:information)", CommandOptionType.SingleValue); app.Option("--debugloglevel", "The severity you log (default:information)", CommandOptionType.SingleValue);
app.Option("--disable-registration", "Disables new user registrations (default:true)", CommandOptionType.SingleValue); app.Option("--disable-registration", "Disables new user registrations (default:true)", CommandOptionType.SingleValue);

View File

@@ -39,6 +39,7 @@ namespace BTCPayServer.Controllers
private RateFetcher _RateProviderFactory; private RateFetcher _RateProviderFactory;
private StoreRepository _StoreRepository; private StoreRepository _StoreRepository;
LightningConfigurationProvider _LnConfigProvider; LightningConfigurationProvider _LnConfigProvider;
private readonly TorServices _torServices;
BTCPayServerOptions _Options; BTCPayServerOptions _Options;
public ServerController(UserManager<ApplicationUser> userManager, public ServerController(UserManager<ApplicationUser> userManager,
@@ -48,6 +49,7 @@ namespace BTCPayServer.Controllers
NBXplorerDashboard dashBoard, NBXplorerDashboard dashBoard,
IHttpClientFactory httpClientFactory, IHttpClientFactory httpClientFactory,
LightningConfigurationProvider lnConfigProvider, LightningConfigurationProvider lnConfigProvider,
TorServices torServices,
Services.Stores.StoreRepository storeRepository) Services.Stores.StoreRepository storeRepository)
{ {
_Options = options; _Options = options;
@@ -58,6 +60,7 @@ namespace BTCPayServer.Controllers
_RateProviderFactory = rateProviderFactory; _RateProviderFactory = rateProviderFactory;
_StoreRepository = storeRepository; _StoreRepository = storeRepository;
_LnConfigProvider = lnConfigProvider; _LnConfigProvider = lnConfigProvider;
_torServices = torServices;
} }
[Route("server/rates")] [Route("server/rates")]
@@ -443,7 +446,7 @@ namespace BTCPayServer.Controllers
} }
[Route("server/services")] [Route("server/services")]
public IActionResult Services() public async Task<IActionResult> Services()
{ {
var result = new ServicesViewModel(); var result = new ServicesViewModel();
result.ExternalServices = _Options.ExternalServices; result.ExternalServices = _Options.ExternalServices;
@@ -463,6 +466,7 @@ namespace BTCPayServer.Controllers
Link = this.Url.Action(nameof(SSHService)) Link = this.Url.Action(nameof(SSHService))
}); });
} }
result.TorServices = await _torServices.GetServices();
return View(result); return View(result);
} }

View File

@@ -62,6 +62,7 @@ namespace BTCPayServer.Hosting
}); });
services.AddHttpClient(); services.AddHttpClient();
services.TryAddSingleton<SettingsRepository>(); services.TryAddSingleton<SettingsRepository>();
services.TryAddSingleton<TorServices>();
services.TryAddSingleton<InvoicePaymentNotification>(); services.TryAddSingleton<InvoicePaymentNotification>();
services.TryAddSingleton<BTCPayServerOptions>(o => o.GetRequiredService<IOptions<BTCPayServerOptions>>().Value); services.TryAddSingleton<BTCPayServerOptions>(o => o.GetRequiredService<IOptions<BTCPayServerOptions>>().Value);
services.TryAddSingleton<InvoiceRepository>(o => services.TryAddSingleton<InvoiceRepository>(o =>

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Configuration; using BTCPayServer.Configuration;
using BTCPayServer.Services;
namespace BTCPayServer.Models.ServerViewModels namespace BTCPayServer.Models.ServerViewModels
{ {
@@ -17,5 +18,6 @@ namespace BTCPayServer.Models.ServerViewModels
public List<ExternalService> ExternalServices { get; set; } = new List<ExternalService>(); public List<ExternalService> ExternalServices { get; set; } = new List<ExternalService>();
public List<OtherExternalService> OtherExternalServices { get; set; } = new List<OtherExternalService>(); public List<OtherExternalService> OtherExternalServices { get; set; } = new List<OtherExternalService>();
public TorService[] TorServices { get; set; } = Array.Empty<TorService>();
} }
} }

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Configuration;
namespace BTCPayServer.Services
{
public class TorServices
{
BTCPayServerOptions _Options;
public TorServices(BTCPayServerOptions options)
{
_Options = options;
}
public async Task<TorService[]> GetServices()
{
if (string.IsNullOrEmpty(_Options.TorHiddenServicesDirectory) || !Directory.Exists(_Options.TorHiddenServicesDirectory))
return Array.Empty<TorService>();
List<TorService> result = new List<TorService>();
var servicesDirs = Directory.GetDirectories(_Options.TorHiddenServicesDirectory);
var services = servicesDirs
.Select(d => new DirectoryInfo(d))
.Select(d => (ServiceName: d.Name, ReadingLines: System.IO.File.ReadAllLinesAsync(Path.Combine(d.FullName, "hostname"))))
.ToArray();
foreach (var service in services)
{
try
{
var onionUrl = (await service.ReadingLines)[0].Trim();
result.Add(new TorService() { Name = service.ServiceName, OnionUrl = onionUrl });
}
catch
{
}
}
return result.ToArray();
}
}
public class TorService
{
public string Name { get; set; }
public string OnionUrl { get; set; }
}
}

View File

@@ -48,35 +48,68 @@
@if (Model.OtherExternalServices.Count != 0) @if (Model.OtherExternalServices.Count != 0)
{ {
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-8">
<h4>Other services</h4> <h4>Other services</h4>
<div class="form-group"> <div class="form-group">
<span>Other external services</span> <span>Other external services</span>
</div> </div>
<div class="form-group"> <div class="form-group">
<table class="table table-sm table-responsive-md"> <table class="table table-sm table-responsive-md">
<thead> <thead>
<tr>
<th>Name</th>
<th style="text-align:right">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.OtherExternalServices)
{
<tr> <tr>
<td>@s.Name</td> <th>Name</th>
<td style="text-align:right"> <th style="text-align:right">Actions</th>
<a href="@s.Link" target="_blank">See information</a>
</td>
</tr> </tr>
} </thead>
</tbody> <tbody>
</table> @foreach (var s in Model.OtherExternalServices)
{
<tr>
<td>@s.Name</td>
<td style="text-align:right">
<a href="@s.Link" target="_blank">See information</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
}
@if (Model.TorServices.Length != 0)
{
<div class="row">
<div class="col-md-8">
<h4>TOR hidden services</h4>
<div class="form-group">
<span>TOR services hosted on this server</span>
</div>
<div class="form-group">
<table class="table table-sm table-responsive-md">
<thead>
<tr>
<th>Name</th>
<th style="text-align:right">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var s in Model.TorServices)
{
<tr>
<td>@s.Name</td>
<td style="text-align:right">
<a href="@s.OnionUrl" target="_blank">See information</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div> </div>
</div> </div>
</div>
} }
@section Scripts { @section Scripts {