mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
.NET 2.0sify, use the same configuration framework as NBXplorer
This commit is contained in:
@@ -77,10 +77,10 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
ServerUri = new Uri("http://127.0.0.1:" + port + "/");
|
ServerUri = new Uri("http://127.0.0.1:" + port + "/");
|
||||||
|
|
||||||
BTCPayServerOptions options = new BTCPayServerOptions();
|
var conf = new DefaultConfiguration() { Logger = Logs.LogProvider.CreateLogger("Console") }.CreateConfiguration(new[] { "--datadir", _Directory });
|
||||||
options.LoadArgs(new TextFileConfiguration(new string[] { "-datadir", _Directory }));
|
|
||||||
|
|
||||||
_Host = new WebHostBuilder()
|
_Host = new WebHostBuilder()
|
||||||
|
.UseConfiguration(conf)
|
||||||
.ConfigureServices(s =>
|
.ConfigureServices(s =>
|
||||||
{
|
{
|
||||||
s.AddSingleton<IRateProvider>(new MockRateProvider(new Rate("USD", 5000m)));
|
s.AddSingleton<IRateProvider>(new MockRateProvider(new Rate("USD", 5000m)));
|
||||||
@@ -91,7 +91,6 @@ namespace BTCPayServer.Tests
|
|||||||
.AddProvider(Logs.LogProvider);
|
.AddProvider(Logs.LogProvider);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.AddPayServer(options)
|
|
||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.Build();
|
.Build();
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace BTCPayServer.Tests
|
|||||||
config.AppendLine($"rpc.auth={Node.AuthenticationString}");
|
config.AppendLine($"rpc.auth={Node.AuthenticationString}");
|
||||||
config.AppendLine($"node.endpoint={Node.NodeEndpoint.Address}:{Node.NodeEndpoint.Port}");
|
config.AppendLine($"node.endpoint={Node.NodeEndpoint.Address}:{Node.NodeEndpoint.Port}");
|
||||||
File.WriteAllText(Path.Combine(launcher2.CurrentDirectory, "settings.config"), config.ToString());
|
File.WriteAllText(Path.Combine(launcher2.CurrentDirectory, "settings.config"), config.ToString());
|
||||||
_Process = launcher.Start("dotnet", $"NBXplorer.dll -datadir \"{launcher2.CurrentDirectory}\"");
|
_Process = launcher.Start("dotnet", $"NBXplorer.dll --datadir \"{launcher2.CurrentDirectory}\"");
|
||||||
ExplorerClient = new NBXplorer.ExplorerClient(Node.Network, new Uri($"http://127.0.0.1:{port}/"));
|
ExplorerClient = new NBXplorer.ExplorerClient(Node.Network, new Uri($"http://127.0.0.1:{port}/"));
|
||||||
CookieFile = Path.Combine(launcher2.CurrentDirectory, ".cookie");
|
CookieFile = Path.Combine(launcher2.CurrentDirectory, ".cookie");
|
||||||
File.Create(CookieFile).Close(); //Will be wipedout when the client starts
|
File.Create(CookieFile).Close(); //Will be wipedout when the client starts
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
<PackageReference Include="NBitpayClient" Version="1.0.0.6" />
|
<PackageReference Include="NBitpayClient" Version="1.0.0.6" />
|
||||||
<PackageReference Include="DBreeze" Version="1.87.0" />
|
<PackageReference Include="DBreeze" Version="1.87.0" />
|
||||||
<PackageReference Include="NBXplorer.Client" Version="1.0.0.12" />
|
<PackageReference Include="NBXplorer.Client" Version="1.0.0.12" />
|
||||||
|
<PackageReference Include="NicolasDorier.CommandLine" Version="1.0.0.1" />
|
||||||
|
<PackageReference Include="NicolasDorier.CommandLine.Configuration" Version="1.0.0.1" />
|
||||||
|
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.9" />
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
|
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
|
||||||
<PackageReference Include="System.Xml.XmlSerializer" Version="4.0.11" />
|
<PackageReference Include="System.Xml.XmlSerializer" Version="4.0.11" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using StandardConfiguration;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace BTCPayServer.Configuration
|
namespace BTCPayServer.Configuration
|
||||||
{
|
{
|
||||||
@@ -41,75 +43,20 @@ namespace BTCPayServer.Configuration
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadArgs(TextFileConfiguration consoleConfig)
|
public void LoadArgs(IConfiguration conf)
|
||||||
{
|
{
|
||||||
ConfigurationFile = consoleConfig.GetOrDefault<string>("conf", null);
|
var networkInfo = DefaultConfiguration.GetNetwork(conf);
|
||||||
DataDir = consoleConfig.GetOrDefault<string>("datadir", null);
|
Network = networkInfo?.Network;
|
||||||
if(DataDir != null && ConfigurationFile != null)
|
if(Network == null)
|
||||||
{
|
throw new ConfigException("Invalid network");
|
||||||
var isRelativePath = Path.GetFullPath(ConfigurationFile).Length > ConfigurationFile.Length;
|
|
||||||
if(isRelativePath)
|
|
||||||
{
|
|
||||||
ConfigurationFile = Path.Combine(DataDir, ConfigurationFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Network = consoleConfig.GetOrDefault<bool>("testnet", false) ? Network.TestNet :
|
|
||||||
consoleConfig.GetOrDefault<bool>("regtest", false) ? Network.RegTest :
|
|
||||||
null;
|
|
||||||
|
|
||||||
if(DataDir != null && ConfigurationFile == null)
|
|
||||||
{
|
|
||||||
ConfigurationFile = GetDefaultConfigurationFile(Network != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ConfigurationFile != null)
|
|
||||||
{
|
|
||||||
AssetConfigFileExists();
|
|
||||||
var configTemp = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));
|
|
||||||
Network = Network ?? (configTemp.GetOrDefault<bool>("testnet", false) ? Network.TestNet :
|
|
||||||
configTemp.GetOrDefault<bool>("regtest", false) ? Network.RegTest :
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
|
|
||||||
Network = Network ?? Network.Main;
|
|
||||||
if(DataDir == null)
|
|
||||||
{
|
|
||||||
DataDir = DefaultDataDirectory.GetDefaultDirectory("BTCPayServer", Network, true);
|
|
||||||
ConfigurationFile = GetDefaultConfigurationFile(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!Directory.Exists(DataDir))
|
|
||||||
throw new ConfigurationException("Data directory does not exists");
|
|
||||||
|
|
||||||
var config = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));
|
|
||||||
consoleConfig.MergeInto(config, true);
|
|
||||||
|
|
||||||
|
DataDir = conf.GetOrDefault<string>("datadir", networkInfo.DefaultDataDirectory);
|
||||||
Logs.Configuration.LogInformation("Network: " + Network);
|
Logs.Configuration.LogInformation("Network: " + Network);
|
||||||
Logs.Configuration.LogInformation("Data directory set to " + DataDir);
|
|
||||||
Logs.Configuration.LogInformation("Configuration file set to " + ConfigurationFile);
|
|
||||||
|
|
||||||
var defaultPort = config.GetOrDefault<int>("port", GetDefaultPort(Network));
|
Explorer = conf.GetOrDefault<Uri>("explorer.url", networkInfo.DefaultExplorerUrl);
|
||||||
Listen = config
|
CookieFile = conf.GetOrDefault<string>("explorer.cookiefile", networkInfo.DefaultExplorerCookieFile);
|
||||||
.GetAll("bind")
|
ExternalUrl = conf.GetOrDefault<Uri>("externalurl", null);
|
||||||
.Select(p => ConvertToEndpoint(p, defaultPort))
|
RequireHttps = conf.GetOrDefault<bool>("requirehttps", false);
|
||||||
.ToList();
|
|
||||||
if(Listen.Count == 0)
|
|
||||||
{
|
|
||||||
Listen.Add(new IPEndPoint(IPAddress.Parse("127.0.0.1"), defaultPort));
|
|
||||||
}
|
|
||||||
|
|
||||||
Explorer = config.GetOrDefault<Uri>("explorer.url", GetDefaultNXplorerUri());
|
|
||||||
CookieFile = config.GetOrDefault<string>("explorer.cookiefile", GetExplorerDefaultCookiePath());
|
|
||||||
ExternalUrl = config.GetOrDefault<Uri>("externalurl", null);
|
|
||||||
if(ExternalUrl == null)
|
|
||||||
{
|
|
||||||
var ip = Listen.Where(u => !u.Address.ToString().Equals("0.0.0.0", StringComparison.OrdinalIgnoreCase)).FirstOrDefault()
|
|
||||||
?? new IPEndPoint(IPAddress.Parse("127.0.0.1"), defaultPort);
|
|
||||||
ExternalUrl = new Uri($"http://{ip.Address}:{ip.Port}/");
|
|
||||||
}
|
|
||||||
|
|
||||||
RequireHttps = config.GetOrDefault<bool>("requirehttps", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RequireHttps
|
public bool RequireHttps
|
||||||
@@ -121,92 +68,5 @@ namespace BTCPayServer.Configuration
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Uri GetDefaultNXplorerUri()
|
|
||||||
{
|
|
||||||
return new Uri("http://localhost:" + GetNXplorerDefaultPort(Network));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string[] GetUrls()
|
|
||||||
{
|
|
||||||
return Listen.Select(b => "http://" + b + "/").ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AssetConfigFileExists()
|
|
||||||
{
|
|
||||||
if(!File.Exists(ConfigurationFile))
|
|
||||||
throw new ConfigurationException("Configuration file does not exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IPEndPoint ConvertToEndpoint(string str, int defaultPort)
|
|
||||||
{
|
|
||||||
var portOut = defaultPort;
|
|
||||||
var hostOut = "";
|
|
||||||
int colon = str.LastIndexOf(':');
|
|
||||||
// if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
|
|
||||||
bool fHaveColon = colon != -1;
|
|
||||||
bool fBracketed = fHaveColon && (str[0] == '[' && str[colon - 1] == ']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
|
|
||||||
bool fMultiColon = fHaveColon && (str.LastIndexOf(':', colon - 1) != -1);
|
|
||||||
if(fHaveColon && (colon == 0 || fBracketed || !fMultiColon))
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
if(int.TryParse(str.Substring(colon + 1), out n) && n > 0 && n < 0x10000)
|
|
||||||
{
|
|
||||||
str = str.Substring(0, colon);
|
|
||||||
portOut = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(str.Length > 0 && str[0] == '[' && str[str.Length - 1] == ']')
|
|
||||||
hostOut = str.Substring(1, str.Length - 2);
|
|
||||||
else
|
|
||||||
hostOut = str;
|
|
||||||
return new IPEndPoint(IPAddress.Parse(hostOut), portOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
const string DefaultConfigFile = "settings.config";
|
|
||||||
private string GetDefaultConfigurationFile(bool createIfNotExist)
|
|
||||||
{
|
|
||||||
var config = Path.Combine(DataDir, DefaultConfigFile);
|
|
||||||
Logs.Configuration.LogInformation("Configuration file set to " + config);
|
|
||||||
if(createIfNotExist && !File.Exists(config))
|
|
||||||
{
|
|
||||||
Logs.Configuration.LogInformation("Creating configuration file");
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.AppendLine("### Global settings ###");
|
|
||||||
builder.AppendLine("#testnet=0");
|
|
||||||
builder.AppendLine("#regtest=0");
|
|
||||||
builder.AppendLine("#Put here the xpub key of your hardware wallet");
|
|
||||||
builder.AppendLine("#hdpubkey=xpub...");
|
|
||||||
builder.AppendLine();
|
|
||||||
builder.AppendLine("### Server settings ###");
|
|
||||||
builder.AppendLine("#port=" + GetDefaultPort(Network));
|
|
||||||
builder.AppendLine("#bind=127.0.0.1");
|
|
||||||
builder.AppendLine("#externalurl=http://127.0.0.1/");
|
|
||||||
builder.AppendLine();
|
|
||||||
builder.AppendLine("### NBXplorer settings ###");
|
|
||||||
builder.AppendLine("#explorer.url=" + GetDefaultNXplorerUri());
|
|
||||||
builder.AppendLine("#explorer.cookiefile=" + GetExplorerDefaultCookiePath());
|
|
||||||
File.WriteAllText(config, builder.ToString());
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetExplorerDefaultCookiePath()
|
|
||||||
{
|
|
||||||
return Path.Combine(DefaultDataDirectory.GetDefaultDirectory("NBXplorer", Network, false), ".cookie");
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetNXplorerDefaultPort(Network network)
|
|
||||||
{
|
|
||||||
return network == Network.Main ? 24444 :
|
|
||||||
network == Network.TestNet ? 24445 : 24446;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetDefaultPort(Network network)
|
|
||||||
{
|
|
||||||
return network == Network.Main ? 23000 :
|
|
||||||
network == Network.TestNet ? 23001 : 23002;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace BTCPayServer.Configuration
|
|||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch(Exception ex)
|
||||||
{
|
{
|
||||||
throw new ConfigurationException($"Could not connect to NBXplorer, {ex.Message}");
|
throw new ConfigException($"Could not connect to NBXplorer, {ex.Message}");
|
||||||
}
|
}
|
||||||
DBreezeEngine db = new DBreezeEngine(CreateDBPath(opts, "TokensDB"));
|
DBreezeEngine db = new DBreezeEngine(CreateDBPath(opts, "TokensDB"));
|
||||||
_Resources.Add(db);
|
_Resources.Add(db);
|
||||||
|
|||||||
15
BTCPayServer/Configuration/ConfigException.cs
Normal file
15
BTCPayServer/Configuration/ConfigException.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Configuration
|
||||||
|
{
|
||||||
|
public class ConfigException : Exception
|
||||||
|
{
|
||||||
|
public ConfigException(string message) : base(message)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
BTCPayServer/Configuration/ConfigurationExtensions.cs
Normal file
52
BTCPayServer/Configuration/ConfigurationExtensions.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Configuration
|
||||||
|
{
|
||||||
|
public static class ConfigurationExtensions
|
||||||
|
{
|
||||||
|
public static T GetOrDefault<T>(this IConfiguration configuration, string key, T defaultValue)
|
||||||
|
{
|
||||||
|
var str = configuration[key] ?? configuration[key.Replace(".", string.Empty)];
|
||||||
|
if(str == null)
|
||||||
|
return defaultValue;
|
||||||
|
if(typeof(T) == typeof(bool))
|
||||||
|
{
|
||||||
|
var trueValues = new[] { "1", "true" };
|
||||||
|
var falseValues = new[] { "0", "false" };
|
||||||
|
if(trueValues.Contains(str, StringComparer.OrdinalIgnoreCase))
|
||||||
|
return (T)(object)true;
|
||||||
|
if(falseValues.Contains(str, StringComparer.OrdinalIgnoreCase))
|
||||||
|
return (T)(object)false;
|
||||||
|
throw new FormatException();
|
||||||
|
}
|
||||||
|
else if(typeof(T) == typeof(Uri))
|
||||||
|
return (T)(object)new Uri(str, UriKind.Absolute);
|
||||||
|
else if(typeof(T) == typeof(string))
|
||||||
|
return (T)(object)str;
|
||||||
|
else if(typeof(T) == typeof(IPEndPoint))
|
||||||
|
{
|
||||||
|
var separator = str.LastIndexOf(":");
|
||||||
|
if(separator == -1)
|
||||||
|
throw new FormatException();
|
||||||
|
var ip = str.Substring(0, separator);
|
||||||
|
var port = str.Substring(separator + 1);
|
||||||
|
return (T)(object)new IPEndPoint(IPAddress.Parse(ip), int.Parse(port));
|
||||||
|
}
|
||||||
|
else if(typeof(T) == typeof(int))
|
||||||
|
{
|
||||||
|
return (T)(object)int.Parse(str, CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Configuration value does not support time " + typeof(T).Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
BTCPayServer/Configuration/DefaultConfiguration.cs
Normal file
96
BTCPayServer/Configuration/DefaultConfiguration.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NBitcoin;
|
||||||
|
using System.Text;
|
||||||
|
using CommandLine;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Configuration
|
||||||
|
{
|
||||||
|
public class DefaultConfiguration : StandardConfiguration.DefaultConfiguration
|
||||||
|
{
|
||||||
|
protected override CommandLineApplication CreateCommandLineApplicationCore()
|
||||||
|
{
|
||||||
|
CommandLineApplication app = new CommandLineApplication(true)
|
||||||
|
{
|
||||||
|
FullName = "NBXplorer\r\nLightweight block explorer for tracking HD wallets",
|
||||||
|
Name = "NBXplorer"
|
||||||
|
};
|
||||||
|
app.HelpOption("-? | -h | --help");
|
||||||
|
app.Option("-n | --network", $"Set the network among ({NetworkInformation.ToStringAll()}) (default: {Network.Main.ToString()})", CommandOptionType.SingleValue);
|
||||||
|
app.Option("--testnet | -testnet", $"Use testnet", CommandOptionType.BoolValue);
|
||||||
|
app.Option("--regtest | -regtest", $"Use regtest", CommandOptionType.BoolValue);
|
||||||
|
app.Option("--requirehttps", $"Will redirect to https version of the website (default: false)", CommandOptionType.BoolValue);
|
||||||
|
app.Option("--externalurl", $"The external url of the website", CommandOptionType.SingleValue);
|
||||||
|
app.Option("--explorerurl", $"Url of the NBxplorer (default: : Default setting of NBXplorer for the network)", CommandOptionType.SingleValue);
|
||||||
|
app.Option("--explorercookiefile", $"Path to the cookie file (default: Default setting of NBXplorer for the network)", CommandOptionType.SingleValue);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetDefaultDataDir(IConfiguration conf)
|
||||||
|
{
|
||||||
|
return GetNetwork(conf).DefaultDataDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetDefaultConfigurationFile(IConfiguration conf)
|
||||||
|
{
|
||||||
|
var network = GetNetwork(conf);
|
||||||
|
var dataDir = conf["datadir"];
|
||||||
|
if(dataDir == null)
|
||||||
|
return network.DefaultConfigurationFile;
|
||||||
|
var fileName = Path.GetFileName(network.DefaultConfigurationFile);
|
||||||
|
return Path.Combine(dataDir, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkInformation GetNetwork(IConfiguration conf)
|
||||||
|
{
|
||||||
|
var network = conf.GetOrDefault<string>("network", null);
|
||||||
|
if(network != null)
|
||||||
|
{
|
||||||
|
var info = NetworkInformation.GetNetworkByName(network);
|
||||||
|
if(info == null)
|
||||||
|
throw new ConfigException($"Invalid network name {network}");
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
var net = conf.GetOrDefault<bool>("regtest", false) ? Network.RegTest :
|
||||||
|
conf.GetOrDefault<bool>("testnet", false) ? Network.TestNet : Network.Main;
|
||||||
|
|
||||||
|
return NetworkInformation.GetNetworkByName(net.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string GetDefaultConfigurationFileTemplate(IConfiguration conf)
|
||||||
|
{
|
||||||
|
var network = GetNetwork(conf);
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.AppendLine("### Global settings ###");
|
||||||
|
builder.AppendLine("#testnet=0");
|
||||||
|
builder.AppendLine("#regtest=0");
|
||||||
|
builder.AppendLine();
|
||||||
|
builder.AppendLine("### Server settings ###");
|
||||||
|
builder.AppendLine("#requirehttps=0");
|
||||||
|
builder.AppendLine("#port=" + network.DefaultPort);
|
||||||
|
builder.AppendLine("#bind=127.0.0.1");
|
||||||
|
builder.AppendLine("#externalurl=http://127.0.0.1/");
|
||||||
|
builder.AppendLine();
|
||||||
|
builder.AppendLine("### NBXplorer settings ###");
|
||||||
|
builder.AppendLine("#explorer.url=" + network.DefaultExplorerUrl.AbsoluteUri);
|
||||||
|
builder.AppendLine("#explorer.cookiefile=" + network.DefaultExplorerCookieFile);
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected override IPEndPoint GetDefaultEndpoint(IConfiguration conf)
|
||||||
|
{
|
||||||
|
return new IPEndPoint(IPAddress.Parse("127.0.0.1"), GetNetwork(conf).DefaultPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
using BTCPayServer.Logging;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using NBitcoin;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Configuration
|
|
||||||
{
|
|
||||||
public class DefaultDataDirectory
|
|
||||||
{
|
|
||||||
public static string GetDefaultDirectory(string appName, Network network, bool createDirectory)
|
|
||||||
{
|
|
||||||
string directory = null;
|
|
||||||
var home = Environment.GetEnvironmentVariable("HOME");
|
|
||||||
if(!string.IsNullOrEmpty(home))
|
|
||||||
{
|
|
||||||
if(createDirectory)
|
|
||||||
Logs.Configuration.LogInformation("Using HOME environment variable for initializing application data");
|
|
||||||
directory = home;
|
|
||||||
directory = Path.Combine(directory, "." + appName.ToLowerInvariant());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var localAppData = Environment.GetEnvironmentVariable("APPDATA");
|
|
||||||
if(!string.IsNullOrEmpty(localAppData))
|
|
||||||
{
|
|
||||||
if(createDirectory)
|
|
||||||
Logs.Configuration.LogInformation("Using APPDATA environment variable for initializing application data");
|
|
||||||
directory = localAppData;
|
|
||||||
directory = Path.Combine(directory, appName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new DirectoryNotFoundException("Could not find suitable datadir");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!Directory.Exists(directory) && createDirectory)
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(directory);
|
|
||||||
}
|
|
||||||
directory = Path.Combine(directory, network.Name);
|
|
||||||
if(!Directory.Exists(directory) && createDirectory)
|
|
||||||
{
|
|
||||||
Logs.Configuration.LogInformation("Creating data directory");
|
|
||||||
Directory.CreateDirectory(directory);
|
|
||||||
}
|
|
||||||
return directory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
103
BTCPayServer/Configuration/NetworkInformation.cs
Normal file
103
BTCPayServer/Configuration/NetworkInformation.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using NBitcoin;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Configuration
|
||||||
|
{
|
||||||
|
public class NetworkInformation
|
||||||
|
{
|
||||||
|
static NetworkInformation()
|
||||||
|
{
|
||||||
|
_Networks = new Dictionary<string, NetworkInformation>();
|
||||||
|
foreach(var network in Network.GetNetworks())
|
||||||
|
{
|
||||||
|
NetworkInformation info = new NetworkInformation();
|
||||||
|
info.DefaultDataDirectory = StandardConfiguration.DefaultDataDirectory.GetDirectory("BTCPayServer", network.Name);
|
||||||
|
info.DefaultConfigurationFile = Path.Combine(info.DefaultDataDirectory, "settings.config");
|
||||||
|
info.DefaultExplorerCookieFile = Path.Combine(StandardConfiguration.DefaultDataDirectory.GetDirectory("NBXplorer", network.Name, false), ".cookie");
|
||||||
|
info.Network = network;
|
||||||
|
info.DefaultExplorerUrl = new Uri("http://127.0.0.1:24446", UriKind.Absolute);
|
||||||
|
info.DefaultPort = 23002;
|
||||||
|
_Networks.Add(network.Name, info);
|
||||||
|
if(network == Network.Main)
|
||||||
|
{
|
||||||
|
info.DefaultExplorerUrl = new Uri("http://127.0.0.1:24444", UriKind.Absolute);
|
||||||
|
Main = info;
|
||||||
|
info.DefaultPort = 23000;
|
||||||
|
}
|
||||||
|
if(network == Network.TestNet)
|
||||||
|
{
|
||||||
|
info.DefaultExplorerUrl = new Uri("http://127.0.0.1:24445", UriKind.Absolute);
|
||||||
|
info.DefaultPort = 23001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Dictionary<string, NetworkInformation> _Networks;
|
||||||
|
public static NetworkInformation GetNetworkByName(string name)
|
||||||
|
{
|
||||||
|
var value = _Networks.TryGet(name);
|
||||||
|
if(value != null)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
//Maybe alias ?
|
||||||
|
var network = Network.GetNetwork(name);
|
||||||
|
if(network != null)
|
||||||
|
{
|
||||||
|
value = _Networks.TryGet(network.Name);
|
||||||
|
if(value != null)
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkInformation Main
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public Network Network
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
public string DefaultConfigurationFile
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public string DefaultDataDirectory
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public Uri DefaultExplorerUrl
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
public int DefaultPort
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
public string DefaultExplorerCookieFile
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Network.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToStringAll()
|
||||||
|
{
|
||||||
|
return string.Join(", ", _Networks.Select(n => n.Key).ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
using NBitcoin;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace BTCPayServer
|
|
||||||
{
|
|
||||||
public class ConfigurationException : Exception
|
|
||||||
{
|
|
||||||
public ConfigurationException(string message) : base(message)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TextFileConfiguration
|
|
||||||
{
|
|
||||||
private Dictionary<string, List<string>> _Args;
|
|
||||||
|
|
||||||
public TextFileConfiguration(string[] args)
|
|
||||||
{
|
|
||||||
_Args = new Dictionary<string, List<string>>();
|
|
||||||
string noValueParam = null;
|
|
||||||
Action flushNoValueParam = () =>
|
|
||||||
{
|
|
||||||
if(noValueParam != null)
|
|
||||||
{
|
|
||||||
Add(noValueParam, "1", false);
|
|
||||||
noValueParam = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach(var arg in args)
|
|
||||||
{
|
|
||||||
bool isParamName = arg.StartsWith("-", StringComparison.Ordinal);
|
|
||||||
if(isParamName)
|
|
||||||
{
|
|
||||||
var splitted = arg.Split('=');
|
|
||||||
if(splitted.Length > 1)
|
|
||||||
{
|
|
||||||
var value = String.Join("=", splitted.Skip(1).ToArray());
|
|
||||||
flushNoValueParam();
|
|
||||||
Add(splitted[0], value, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flushNoValueParam();
|
|
||||||
noValueParam = splitted[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(noValueParam != null)
|
|
||||||
{
|
|
||||||
Add(noValueParam, arg, false);
|
|
||||||
noValueParam = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flushNoValueParam();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Add(string key, string value, bool sourcePriority)
|
|
||||||
{
|
|
||||||
key = NormalizeKey(key);
|
|
||||||
List<string> list;
|
|
||||||
if(!_Args.TryGetValue(key, out list))
|
|
||||||
{
|
|
||||||
list = new List<string>();
|
|
||||||
_Args.Add(key, list);
|
|
||||||
}
|
|
||||||
if(sourcePriority)
|
|
||||||
list.Insert(0, value);
|
|
||||||
else
|
|
||||||
list.Add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string NormalizeKey(string key)
|
|
||||||
{
|
|
||||||
key = key.ToLowerInvariant();
|
|
||||||
while(key.Length > 0 && key[0] == '-')
|
|
||||||
{
|
|
||||||
key = key.Substring(1);
|
|
||||||
}
|
|
||||||
key = key.Replace(".", "");
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void MergeInto(TextFileConfiguration destination, bool sourcePriority)
|
|
||||||
{
|
|
||||||
foreach(var kv in _Args)
|
|
||||||
{
|
|
||||||
foreach(var v in kv.Value)
|
|
||||||
destination.Add(kv.Key, v, sourcePriority);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextFileConfiguration(Dictionary<string, List<string>> args)
|
|
||||||
{
|
|
||||||
_Args = args;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TextFileConfiguration Parse(string data)
|
|
||||||
{
|
|
||||||
Dictionary<string, List<string>> result = new Dictionary<string, List<string>>();
|
|
||||||
var lines = data.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
int lineCount = -1;
|
|
||||||
foreach(var l in lines)
|
|
||||||
{
|
|
||||||
lineCount++;
|
|
||||||
var line = l.Trim();
|
|
||||||
if(line.StartsWith("#", StringComparison.Ordinal))
|
|
||||||
continue;
|
|
||||||
var split = line.Split('=');
|
|
||||||
if(split.Length == 0)
|
|
||||||
continue;
|
|
||||||
if(split.Length == 1)
|
|
||||||
throw new FormatException("Line " + lineCount + ": No value are set");
|
|
||||||
|
|
||||||
var key = split[0];
|
|
||||||
key = NormalizeKey(key);
|
|
||||||
List<string> values;
|
|
||||||
if(!result.TryGetValue(key, out values))
|
|
||||||
{
|
|
||||||
values = new List<string>();
|
|
||||||
result.Add(key, values);
|
|
||||||
}
|
|
||||||
var value = String.Join("=", split.Skip(1).ToArray());
|
|
||||||
values.Add(value);
|
|
||||||
}
|
|
||||||
return new TextFileConfiguration(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Contains(string key)
|
|
||||||
{
|
|
||||||
List<string> values;
|
|
||||||
return _Args.TryGetValue(key, out values);
|
|
||||||
}
|
|
||||||
public string[] GetAll(string key)
|
|
||||||
{
|
|
||||||
List<string> values;
|
|
||||||
if(!_Args.TryGetValue(key, out values))
|
|
||||||
return new string[0];
|
|
||||||
return values.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Tuple<string, string>> _Aliases = new List<Tuple<string, string>>();
|
|
||||||
|
|
||||||
public void AddAlias(string from, string to)
|
|
||||||
{
|
|
||||||
from = NormalizeKey(from);
|
|
||||||
to = NormalizeKey(to);
|
|
||||||
_Aliases.Add(Tuple.Create(from, to));
|
|
||||||
}
|
|
||||||
public T GetOrDefault<T>(string key, T defaultValue)
|
|
||||||
{
|
|
||||||
key = NormalizeKey(key);
|
|
||||||
|
|
||||||
var aliases = _Aliases
|
|
||||||
.Where(a => a.Item1 == key || a.Item2 == key)
|
|
||||||
.Select(a => a.Item1 == key ? a.Item2 : a.Item1)
|
|
||||||
.ToList();
|
|
||||||
aliases.Insert(0, key);
|
|
||||||
|
|
||||||
foreach(var alias in aliases)
|
|
||||||
{
|
|
||||||
List<string> values;
|
|
||||||
if(!_Args.TryGetValue(alias, out values))
|
|
||||||
continue;
|
|
||||||
if(values.Count == 0)
|
|
||||||
continue;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return ConvertValue<T>(values[0]);
|
|
||||||
}
|
|
||||||
catch(FormatException) { throw new ConfigurationException("Key " + key + " should be of type " + typeof(T).Name); }
|
|
||||||
}
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private T ConvertValue<T>(string str)
|
|
||||||
{
|
|
||||||
if(typeof(T) == typeof(bool))
|
|
||||||
{
|
|
||||||
var trueValues = new[] { "1", "true" };
|
|
||||||
var falseValues = new[] { "0", "false" };
|
|
||||||
if(trueValues.Contains(str, StringComparer.OrdinalIgnoreCase))
|
|
||||||
return (T)(object)true;
|
|
||||||
if(falseValues.Contains(str, StringComparer.OrdinalIgnoreCase))
|
|
||||||
return (T)(object)false;
|
|
||||||
throw new FormatException();
|
|
||||||
}
|
|
||||||
else if(typeof(T) == typeof(Uri))
|
|
||||||
return (T)(object)new Uri(str, UriKind.Absolute);
|
|
||||||
else if(typeof(T) == typeof(string))
|
|
||||||
return (T)(object)str;
|
|
||||||
else if(typeof(T) == typeof(IPEndPoint))
|
|
||||||
{
|
|
||||||
var separator = str.LastIndexOf(":");
|
|
||||||
if(separator == -1)
|
|
||||||
throw new FormatException();
|
|
||||||
var ip = str.Substring(0, separator);
|
|
||||||
var port = str.Substring(separator + 1);
|
|
||||||
return (T)(object)new IPEndPoint(IPAddress.Parse(ip), int.Parse(port));
|
|
||||||
}
|
|
||||||
else if(typeof(T) == typeof(int))
|
|
||||||
{
|
|
||||||
return (T)(object)int.Parse(str, CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Configuration value does not support time " + typeof(T).Name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
using BTCPayServer.Authentication;
|
using BTCPayServer.Authentication;
|
||||||
|
using BTCPayServer.Configuration;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -8,6 +11,17 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public static IServiceCollection ConfigureBTCPayServer(this IServiceCollection services, IConfiguration conf)
|
||||||
|
{
|
||||||
|
services.Configure<BTCPayServerOptions>(o =>
|
||||||
|
{
|
||||||
|
o.LoadArgs(conf);
|
||||||
|
});
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static BitIdentity GetBitIdentity(this Controller controller)
|
public static BitIdentity GetBitIdentity(this Controller controller)
|
||||||
{
|
{
|
||||||
if(!(controller.User.Identity is BitIdentity))
|
if(!(controller.User.Identity is BitIdentity))
|
||||||
|
|||||||
@@ -22,70 +22,142 @@ using BTCPayServer.Services.Stores;
|
|||||||
using BTCPayServer.Services.Fees;
|
using BTCPayServer.Services.Fees;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Rewrite;
|
using Microsoft.AspNetCore.Rewrite;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using BTCPayServer.Controllers;
|
||||||
|
using BTCPayServer.Services.Mails;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using BTCPayServer.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace BTCPayServer.Hosting
|
namespace BTCPayServer.Hosting
|
||||||
{
|
{
|
||||||
public static class BTCPayServerServices
|
public static class BTCPayServerServices
|
||||||
{
|
{
|
||||||
public static IWebHostBuilder AddPayServer(this IWebHostBuilder builder, BTCPayServerOptions options)
|
public class OwnStoreAuthorizationRequirement : IAuthorizationRequirement
|
||||||
{
|
{
|
||||||
return
|
public OwnStoreAuthorizationRequirement()
|
||||||
builder
|
|
||||||
.ConfigureServices(c =>
|
|
||||||
{
|
{
|
||||||
c.AddDbContext<ApplicationDbContext>(o =>
|
|
||||||
{
|
|
||||||
var path = Path.Combine(options.DataDir, "sqllite.db");
|
|
||||||
o.UseSqlite("Data Source=" + path);
|
|
||||||
});
|
|
||||||
c.AddSingleton(options);
|
|
||||||
c.AddSingleton<BTCPayServerRuntime>(o =>
|
|
||||||
{
|
|
||||||
var runtime = new BTCPayServerRuntime();
|
|
||||||
runtime.Configure(options);
|
|
||||||
return runtime;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(options.RequireHttps)
|
|
||||||
{
|
|
||||||
c.Configure<MvcOptions>(o =>
|
|
||||||
{
|
|
||||||
o.Filters.Add(new RequireHttpsAttribute());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.AddSingleton<Network>(options.Network);
|
public OwnStoreAuthorizationRequirement(string role)
|
||||||
c.AddSingleton(o => o.GetRequiredService<BTCPayServerRuntime>().TokenRepository);
|
{
|
||||||
c.AddSingleton(o => o.GetRequiredService<BTCPayServerRuntime>().InvoiceRepository);
|
Role = role;
|
||||||
c.AddSingleton<ApplicationDbContextFactory>(o => o.GetRequiredService<BTCPayServerRuntime>().DBFactory);
|
}
|
||||||
c.AddSingleton<StoreRepository>();
|
|
||||||
c.AddSingleton(o => o.GetRequiredService<BTCPayServerRuntime>().Wallet);
|
public string Role
|
||||||
c.AddSingleton<CurrencyNameTable>();
|
{
|
||||||
c.AddSingleton<IFeeProvider>(o => new NBXplorerFeeProvider()
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OwnStoreHandler : AuthorizationHandler<OwnStoreAuthorizationRequirement>
|
||||||
|
{
|
||||||
|
StoreRepository _StoreRepository;
|
||||||
|
UserManager<ApplicationUser> _UserManager;
|
||||||
|
public OwnStoreHandler(StoreRepository storeRepository, UserManager<ApplicationUser> userManager)
|
||||||
|
{
|
||||||
|
_StoreRepository = storeRepository;
|
||||||
|
_UserManager = userManager;
|
||||||
|
}
|
||||||
|
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OwnStoreAuthorizationRequirement requirement)
|
||||||
|
{
|
||||||
|
object storeId = null;
|
||||||
|
if(!((Microsoft.AspNetCore.Mvc.ActionContext)context.Resource).RouteData.Values.TryGetValue("storeId", out storeId))
|
||||||
|
context.Succeed(requirement);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var store = await _StoreRepository.FindStore((string)storeId, _UserManager.GetUserId(((Microsoft.AspNetCore.Mvc.ActionContext)context.Resource).HttpContext.User));
|
||||||
|
if(store != null)
|
||||||
|
if(requirement.Role == null || requirement.Role == store.Role)
|
||||||
|
context.Succeed(requirement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class BTCPayServerConfigureOptions : IConfigureOptions<MvcOptions>
|
||||||
|
{
|
||||||
|
BTCPayServerOptions _Options;
|
||||||
|
public BTCPayServerConfigureOptions(BTCPayServerOptions options)
|
||||||
|
{
|
||||||
|
_Options = options;
|
||||||
|
}
|
||||||
|
public void Configure(MvcOptions options)
|
||||||
|
{
|
||||||
|
if(_Options.RequireHttps)
|
||||||
|
options.Filters.Add(new RequireHttpsAttribute());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static IServiceCollection AddBTCPayServer(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddDbContext<ApplicationDbContext>((provider, o) =>
|
||||||
|
{
|
||||||
|
var path = Path.Combine(provider.GetRequiredService<BTCPayServerOptions>().DataDir, "sqllite.db");
|
||||||
|
o.UseSqlite("Data Source=" + path);
|
||||||
|
});
|
||||||
|
services.TryAddSingleton<BTCPayServerOptions>(o => o.GetRequiredService<IOptions<BTCPayServerOptions>>().Value);
|
||||||
|
services.TryAddSingleton<IConfigureOptions<MvcOptions>, BTCPayServerConfigureOptions>();
|
||||||
|
services.TryAddSingleton(o =>
|
||||||
|
{
|
||||||
|
var runtime = new BTCPayServerRuntime();
|
||||||
|
runtime.Configure(o.GetRequiredService<BTCPayServerOptions>());
|
||||||
|
return runtime;
|
||||||
|
});
|
||||||
|
services.TryAddSingleton(o => o.GetRequiredService<BTCPayServerRuntime>().TokenRepository);
|
||||||
|
services.TryAddSingleton(o => o.GetRequiredService<BTCPayServerRuntime>().InvoiceRepository);
|
||||||
|
services.TryAddSingleton<Network>(o => o.GetRequiredService<BTCPayServerOptions>().Network);
|
||||||
|
services.TryAddSingleton<ApplicationDbContextFactory>(o => o.GetRequiredService<BTCPayServerRuntime>().DBFactory);
|
||||||
|
services.TryAddSingleton<StoreRepository>();
|
||||||
|
services.TryAddSingleton(o => o.GetRequiredService<BTCPayServerRuntime>().Wallet);
|
||||||
|
services.TryAddSingleton<CurrencyNameTable>();
|
||||||
|
services.TryAddSingleton<IFeeProvider>(o => new NBXplorerFeeProvider()
|
||||||
{
|
{
|
||||||
Fallback = new FeeRate(100, 1),
|
Fallback = new FeeRate(100, 1),
|
||||||
BlockTarget = 20,
|
BlockTarget = 20,
|
||||||
ExplorerClient = o.GetRequiredService<ExplorerClient>()
|
ExplorerClient = o.GetRequiredService<ExplorerClient>()
|
||||||
});
|
});
|
||||||
c.AddSingleton<ExplorerClient>(o =>
|
services.TryAddSingleton<ExplorerClient>(o =>
|
||||||
{
|
{
|
||||||
var runtime = o.GetRequiredService<BTCPayServerRuntime>();
|
var runtime = o.GetRequiredService<BTCPayServerRuntime>();
|
||||||
return runtime.Explorer;
|
return runtime.Explorer;
|
||||||
});
|
});
|
||||||
c.AddSingleton<Bitpay>(o =>
|
services.TryAddSingleton<Bitpay>(o =>
|
||||||
{
|
{
|
||||||
if(options.Network == Network.Main)
|
if(o.GetRequiredService<BTCPayServerOptions>().Network == Network.Main)
|
||||||
return new Bitpay(new Key(), new Uri("https://bitpay.com/"));
|
return new Bitpay(new Key(), new Uri("https://bitpay.com/"));
|
||||||
else
|
else
|
||||||
return new Bitpay(new Key(), new Uri("https://test.bitpay.com/"));
|
return new Bitpay(new Key(), new Uri("https://test.bitpay.com/"));
|
||||||
});
|
});
|
||||||
c.TryAddSingleton<IRateProvider, BitpayRateProvider>();
|
services.TryAddSingleton<IRateProvider, BitpayRateProvider>();
|
||||||
c.AddSingleton<InvoiceWatcher>();
|
services.TryAddSingleton<InvoiceWatcher>();
|
||||||
c.AddSingleton<IHostedService>(o => o.GetRequiredService<InvoiceWatcher>());
|
services.TryAddSingleton<IHostedService>(o => o.GetRequiredService<InvoiceWatcher>());
|
||||||
c.AddScoped<IHttpContextAccessor, HttpContextAccessor>();
|
services.TryAddScoped<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
c.AddSingleton<IExternalUrlProvider>(o => new FixedExternalUrlProvider(options.ExternalUrl, o.GetRequiredService<IHttpContextAccessor>()));
|
services.TryAddSingleton<IExternalUrlProvider>(o =>
|
||||||
})
|
{
|
||||||
.UseUrls(options.GetUrls());
|
var op = o.GetRequiredService<BTCPayServerOptions>();
|
||||||
|
if(op.ExternalUrl != null)
|
||||||
|
return new FixedExternalUrlProvider(op.ExternalUrl, o.GetRequiredService<IHttpContextAccessor>());
|
||||||
|
return new DefaultExternalUrlProvider(o.GetRequiredService<IHttpContextAccessor>());
|
||||||
|
});
|
||||||
|
services.TryAddSingleton<IAuthorizationHandler, OwnStoreHandler>();
|
||||||
|
services.AddTransient<AccessTokenController>();
|
||||||
|
// Add application services.
|
||||||
|
services.AddTransient<IEmailSender, EmailSender>();
|
||||||
|
|
||||||
|
services.AddAuthorization(o =>
|
||||||
|
{
|
||||||
|
o.AddPolicy("CanAccessStore", builder =>
|
||||||
|
{
|
||||||
|
builder.AddRequirements(new OwnStoreAuthorizationRequirement());
|
||||||
|
});
|
||||||
|
|
||||||
|
o.AddPolicy("OwnStore", builder =>
|
||||||
|
{
|
||||||
|
builder.AddRequirements(new OwnStoreAuthorizationRequirement("Owner"));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IApplicationBuilder UsePayServer(this IApplicationBuilder app)
|
public static IApplicationBuilder UsePayServer(this IApplicationBuilder app)
|
||||||
|
|||||||
@@ -23,45 +23,30 @@ using System.Threading.Tasks;
|
|||||||
using BTCPayServer.Controllers;
|
using BTCPayServer.Controllers;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Mails;
|
using BTCPayServer.Services.Mails;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace BTCPayServer.Hosting
|
namespace BTCPayServer.Hosting
|
||||||
{
|
{
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
|
public Startup(IConfiguration conf)
|
||||||
|
{
|
||||||
|
Configuration = conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration Configuration
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
services.ConfigureBTCPayServer(Configuration);
|
||||||
|
|
||||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||||
.AddDefaultTokenProviders();
|
.AddDefaultTokenProviders();
|
||||||
|
|
||||||
services.AddAuthorization(o =>
|
services.AddBTCPayServer();
|
||||||
{
|
|
||||||
o.AddPolicy("CanAccessStore", builder =>
|
|
||||||
{
|
|
||||||
builder.AddRequirements(new OwnStoreAuthorizationRequirement());
|
|
||||||
});
|
|
||||||
|
|
||||||
o.AddPolicy("OwnStore", builder =>
|
|
||||||
{
|
|
||||||
builder.AddRequirements(new OwnStoreAuthorizationRequirement("Owner"));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
services.AddSingleton<IAuthorizationHandler, OwnStoreHandler>();
|
|
||||||
services.AddTransient<AccessTokenController>();
|
|
||||||
// Add application services.
|
|
||||||
services.AddTransient<IEmailSender, EmailSender>();
|
|
||||||
|
|
||||||
//services.AddSingleton<IObjectModelValidator, NoObjectModelValidator>();
|
|
||||||
services.AddMvcCore(o =>
|
|
||||||
{
|
|
||||||
//o.Filters.Add(new NBXplorerExceptionFilter());
|
|
||||||
o.OutputFormatters.Clear();
|
|
||||||
o.InputFormatters.Clear();
|
|
||||||
})
|
|
||||||
.AddJsonFormatters()
|
|
||||||
.AddFormatterMappings();
|
|
||||||
|
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
}
|
}
|
||||||
public void Configure(
|
public void Configure(
|
||||||
@@ -74,6 +59,8 @@ namespace BTCPayServer.Hosting
|
|||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
app.UseBrowserLink();
|
app.UseBrowserLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Logs.Configure(loggerFactory);
|
Logs.Configure(loggerFactory);
|
||||||
app.UsePayServer();
|
app.UsePayServer();
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
@@ -87,45 +74,4 @@ namespace BTCPayServer.Hosting
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OwnStoreAuthorizationRequirement : IAuthorizationRequirement
|
|
||||||
{
|
|
||||||
public OwnStoreAuthorizationRequirement()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public OwnStoreAuthorizationRequirement(string role)
|
|
||||||
{
|
|
||||||
Role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Role
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class OwnStoreHandler : AuthorizationHandler<OwnStoreAuthorizationRequirement>
|
|
||||||
{
|
|
||||||
StoreRepository _StoreRepository;
|
|
||||||
UserManager<ApplicationUser> _UserManager;
|
|
||||||
public OwnStoreHandler(StoreRepository storeRepository, UserManager<ApplicationUser> userManager)
|
|
||||||
{
|
|
||||||
_StoreRepository = storeRepository;
|
|
||||||
_UserManager = userManager;
|
|
||||||
}
|
|
||||||
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, OwnStoreAuthorizationRequirement requirement)
|
|
||||||
{
|
|
||||||
object storeId = null;
|
|
||||||
if(!((Microsoft.AspNetCore.Mvc.ActionContext)context.Resource).RouteData.Values.TryGetValue("storeId", out storeId))
|
|
||||||
context.Succeed(requirement);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var store = await _StoreRepository.FindStore((string)storeId, _UserManager.GetUserId(((Microsoft.AspNetCore.Mvc.ActionContext)context.Resource).HttpContext.User));
|
|
||||||
if(store != null)
|
|
||||||
if(requirement.Role == null || requirement.Role == store.Role)
|
|
||||||
context.Succeed(requirement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ using System.IO;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace BTCPayServer
|
namespace BTCPayServer
|
||||||
{
|
{
|
||||||
@@ -22,18 +24,22 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
ServicePointManager.DefaultConnectionLimit = 100;
|
ServicePointManager.DefaultConnectionLimit = 100;
|
||||||
IWebHost host = null;
|
IWebHost host = null;
|
||||||
|
CustomConsoleLogProvider loggerProvider = new CustomConsoleLogProvider();
|
||||||
|
|
||||||
|
var loggerFactory = new LoggerFactory();
|
||||||
|
loggerFactory.AddProvider(loggerProvider);
|
||||||
|
var logger = loggerFactory.CreateLogger("Configuration");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var conf = new BTCPayServerOptions();
|
var conf = new DefaultConfiguration() { Logger = logger }.CreateConfiguration(args);
|
||||||
var arguments = new TextFileConfiguration(args);
|
if(conf == null)
|
||||||
arguments = LoadEnvironmentVariables(arguments);
|
return;
|
||||||
conf.LoadArgs(arguments);
|
|
||||||
|
|
||||||
host = new WebHostBuilder()
|
host = new WebHostBuilder()
|
||||||
.AddPayServer(conf)
|
|
||||||
.UseKestrel()
|
.UseKestrel()
|
||||||
.UseIISIntegration()
|
.UseIISIntegration()
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseConfiguration(conf)
|
||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
services.AddLogging(l =>
|
services.AddLogging(l =>
|
||||||
@@ -44,11 +50,19 @@ namespace BTCPayServer
|
|||||||
})
|
})
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.Build();
|
.Build();
|
||||||
var running = host.RunAsync();
|
host.StartAsync().GetAwaiter().GetResult();
|
||||||
OpenBrowser(conf.GetUrls().Select(url => url.Replace("0.0.0.0", "127.0.0.1")).First());
|
var urls = host.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
|
||||||
running.GetAwaiter().GetResult();
|
if(urls.Count != 0)
|
||||||
|
{
|
||||||
|
OpenBrowser(urls.Select(url => url.Replace("0.0.0.0", "127.0.0.1")).First());
|
||||||
}
|
}
|
||||||
catch(ConfigurationException ex)
|
foreach(var url in urls)
|
||||||
|
{
|
||||||
|
logger.LogInformation("Listening on " + url);
|
||||||
|
}
|
||||||
|
host.WaitForShutdown();
|
||||||
|
}
|
||||||
|
catch(ConfigException ex)
|
||||||
{
|
{
|
||||||
if(!string.IsNullOrEmpty(ex.Message))
|
if(!string.IsNullOrEmpty(ex.Message))
|
||||||
Logs.Configuration.LogError(ex.Message);
|
Logs.Configuration.LogError(ex.Message);
|
||||||
@@ -62,30 +76,10 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
if(host != null)
|
if(host != null)
|
||||||
host.Dispose();
|
host.Dispose();
|
||||||
|
loggerProvider.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TextFileConfiguration LoadEnvironmentVariables(TextFileConfiguration args)
|
|
||||||
{
|
|
||||||
var variables = Environment.GetEnvironmentVariables();
|
|
||||||
List<string> values = new List<string>();
|
|
||||||
foreach(DictionaryEntry variable in variables)
|
|
||||||
{
|
|
||||||
var key = (string)variable.Key;
|
|
||||||
var value = (string)variable.Value;
|
|
||||||
if(key.StartsWith("APPSETTING_", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
key = key.Substring("APPSETTING_".Length);
|
|
||||||
values.Add("-" + key);
|
|
||||||
values.Add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextFileConfiguration envConfig = new TextFileConfiguration(values.ToArray());
|
|
||||||
args.MergeInto(envConfig, true);
|
|
||||||
return envConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void OpenBrowser(string url)
|
public static void OpenBrowser(string url)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 1.4 KiB |
Reference in New Issue
Block a user