Policies: Cleanup and improvements (#5731)

* Policies: Turn checkboxes into toggles

* Move email policy to server email settings

* Move maintenance policies to server maintenance settings

* Policies: Adjust spacings

* Policies: Remove DisableInstantNotifications setting

* Wording updates

* Move maintenance settings back
This commit is contained in:
d11n 2024-02-21 14:43:44 +01:00 committed by GitHub
parent 55a8ba0905
commit 9c95b98f3a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 356 additions and 311 deletions

View file

@ -2332,7 +2332,7 @@ namespace BTCPayServer.Tests
var setting = await ctx.Settings.FirstOrDefaultAsync(c => c.Id == id);
if (setting != null) ctx.Settings.Remove(setting);
// create legacy policies setting that needs migration
setting = new SettingData { Id = id, Value = JObject.Parse("{\"RootAppId\": null, \"RootAppType\": 1, \"Experimental\": false, \"PluginSource\": null, \"LockSubscription\": false, \"DisableSSHService\": false, \"PluginPreReleases\": false, \"BlockExplorerLinks\": [],\"DomainToAppMapping\": [{\"AppId\": \"87kj5yKay8mB4UUZcJhZH5TqDKMD3CznjwLjiu1oYZXe\", \"Domain\": \"donate.nicolas-dorier.com\", \"AppType\": 0}], \"CheckForNewVersions\": false, \"AllowHotWalletForAll\": false, \"RequiresConfirmedEmail\": false, \"DiscourageSearchEngines\": false, \"DisableInstantNotifications\": false, \"DisableNonAdminCreateUserApi\": false, \"AllowHotWalletRPCImportForAll\": false, \"AllowLightningInternalNodeForAll\": false, \"DisableStoresToUseServerEmailSettings\": false}").ToString() };
setting = new SettingData { Id = id, Value = JObject.Parse("{\"RootAppId\": null, \"RootAppType\": 1, \"Experimental\": false, \"PluginSource\": null, \"LockSubscription\": false, \"DisableSSHService\": false, \"PluginPreReleases\": false, \"BlockExplorerLinks\": [],\"DomainToAppMapping\": [{\"AppId\": \"87kj5yKay8mB4UUZcJhZH5TqDKMD3CznjwLjiu1oYZXe\", \"Domain\": \"donate.nicolas-dorier.com\", \"AppType\": 0}], \"CheckForNewVersions\": false, \"AllowHotWalletForAll\": false, \"RequiresConfirmedEmail\": false, \"DiscourageSearchEngines\": false, \"DisableNonAdminCreateUserApi\": false, \"AllowHotWalletRPCImportForAll\": false, \"AllowLightningInternalNodeForAll\": false, \"DisableStoresToUseServerEmailSettings\": false}").ToString() };
ctx.Settings.Add(setting);
await ctx.SaveChangesAsync();
}

View file

@ -122,21 +122,24 @@ namespace BTCPayServer.Controllers
_transactionLinkProviders = transactionLinkProviders;
}
[Route("server/maintenance")]
[HttpGet("server/maintenance")]
public IActionResult Maintenance()
{
MaintenanceViewModel vm = new MaintenanceViewModel();
vm.CanUseSSH = _sshState.CanUseSSH;
var vm = new MaintenanceViewModel
{
CanUseSSH = _sshState.CanUseSSH,
DNSDomain = Request.Host.Host
};
if (!vm.CanUseSSH)
TempData[WellKnownTempData.ErrorMessage] = "Maintenance feature requires access to SSH properly configured in BTCPay Server configuration.";
vm.DNSDomain = this.Request.Host.Host;
if (IPAddress.TryParse(vm.DNSDomain, out var unused))
vm.DNSDomain = null;
return View(vm);
}
[Route("server/maintenance")]
[HttpPost]
[HttpPost("server/maintenance")]
public async Task<IActionResult> Maintenance(MaintenanceViewModel vm, string command)
{
vm.CanUseSSH = _sshState.CanUseSSH;
@ -302,8 +305,8 @@ namespace BTCPayServer.Controllers
[Route("server/policies")]
public async Task<IActionResult> Policies()
{
ViewBag.AppsList = await GetAppSelectList();
ViewBag.UpdateUrlPresent = _Options.UpdateUrl != null;
ViewBag.AppsList = await GetAppSelectList();
return View(_policiesSettings);
}
@ -1134,13 +1137,17 @@ namespace BTCPayServer.Controllers
[Route("server/emails")]
public async Task<IActionResult> Emails()
{
var data = (await _SettingsRepository.GetSettingAsync<EmailSettings>()) ?? new EmailSettings();
return View(new EmailsViewModel(data));
var email = await _SettingsRepository.GetSettingAsync<EmailSettings>() ?? new EmailSettings();
var vm = new ServerEmailsViewModel(email)
{
EnableStoresToUseServerEmailSettings = !_policiesSettings.DisableStoresToUseServerEmailSettings
};
return View(vm);
}
[Route("server/emails")]
[HttpPost]
public async Task<IActionResult> Emails(EmailsViewModel model, string command)
public async Task<IActionResult> Emails(ServerEmailsViewModel model, string command)
{
if (command == "Test")
{
@ -1170,6 +1177,13 @@ namespace BTCPayServer.Controllers
}
return View(model);
}
if (_policiesSettings.DisableStoresToUseServerEmailSettings == model.EnableStoresToUseServerEmailSettings)
{
_policiesSettings.DisableStoresToUseServerEmailSettings = !model.EnableStoresToUseServerEmailSettings;
await _SettingsRepository.UpdateSetting(_policiesSettings);
}
if (command == "ResetPassword")
{
var settings = await _SettingsRepository.GetSettingAsync<EmailSettings>() ?? new EmailSettings();
@ -1178,22 +1192,22 @@ namespace BTCPayServer.Controllers
TempData[WellKnownTempData.SuccessMessage] = "Email server password reset";
return RedirectToAction(nameof(Emails));
}
else // if (command == "Save")
// save
if (model.Settings.From is not null && !MailboxAddressValidator.IsMailboxAddress(model.Settings.From))
{
if (model.Settings.From is not null && !MailboxAddressValidator.IsMailboxAddress(model.Settings.From))
{
ModelState.AddModelError("Settings.From", "Invalid email");
return View(model);
}
var oldSettings = await _SettingsRepository.GetSettingAsync<EmailSettings>() ?? new EmailSettings();
if (new EmailsViewModel(oldSettings).PasswordSet)
{
model.Settings.Password = oldSettings.Password;
}
await _SettingsRepository.UpdateSetting(model.Settings);
TempData[WellKnownTempData.SuccessMessage] = "Email settings saved";
return RedirectToAction(nameof(Emails));
ModelState.AddModelError("Settings.From", "Invalid email");
return View(model);
}
var oldSettings = await _SettingsRepository.GetSettingAsync<EmailSettings>() ?? new EmailSettings();
if (new EmailsViewModel(oldSettings).PasswordSet)
{
model.Settings.Password = oldSettings.Password;
}
await _SettingsRepository.UpdateSetting(model.Settings);
TempData[WellKnownTempData.SuccessMessage] = "Email settings saved";
return RedirectToAction(nameof(Emails));
}
[Route("server/logs/{file?}")]

View file

@ -7,11 +7,9 @@ using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
using BTCPayServer.Models.ServerViewModels;
using BTCPayServer.Models;
using BTCPayServer.Services.Mails;
using BTCPayServer.Validation;
using Microsoft.AspNetCore.Mvc;
using MimeKit;

View file

@ -0,0 +1,31 @@
using System.ComponentModel.DataAnnotations;
using BTCPayServer.Services.Mails;
using BTCPayServer.Validation;
namespace BTCPayServer.Models;
public class EmailsViewModel
{
public EmailSettings Settings { get; set; }
public EmailSettings FallbackSettings { get; set; }
public bool PasswordSet { get; set; }
[MailboxAddress]
[Display(Name = "Test Email")]
public string TestEmail { get; set; }
public EmailsViewModel()
{
}
public EmailsViewModel(EmailSettings settings, EmailSettings fallbackSettings = null)
{
Settings = settings;
FallbackSettings = fallbackSettings;
PasswordSet = !string.IsNullOrEmpty(settings?.Password);
}
public bool IsSetup() => Settings?.IsComplete() is true;
public bool IsFallbackSetup() => FallbackSettings?.IsComplete() is true;
public bool UsesFallback() => IsFallbackSetup() && Settings == FallbackSettings;
}

View file

@ -1,32 +1,18 @@
using System.ComponentModel.DataAnnotations;
using BTCPayServer.Services.Mails;
using BTCPayServer.Validation;
namespace BTCPayServer.Models.ServerViewModels
namespace BTCPayServer.Models.ServerViewModels;
public class ServerEmailsViewModel : EmailsViewModel
{
public class EmailsViewModel
[Display(Name = "Allow Stores use the Server's SMTP email settings as their default")]
public bool EnableStoresToUseServerEmailSettings { get; set; }
public ServerEmailsViewModel()
{
public EmailSettings Settings { get; set; }
public EmailSettings FallbackSettings { get; set; }
public bool PasswordSet { get; set; }
[MailboxAddress]
[Display(Name = "Test Email")]
public string TestEmail { get; set; }
}
public EmailsViewModel()
{
}
public EmailsViewModel(EmailSettings settings, EmailSettings fallbackSettings = null)
{
Settings = settings;
FallbackSettings = fallbackSettings;
PasswordSet = !string.IsNullOrEmpty(settings?.Password);
}
public bool IsSetup() => Settings?.IsComplete() is true;
public bool IsFallbackSetup() => FallbackSettings?.IsComplete() is true;
public bool UsesFallback() => IsFallbackSetup() && Settings == FallbackSettings;
public ServerEmailsViewModel(EmailSettings settings) : base(settings)
{
}
}

View file

@ -1,11 +1,10 @@
using System.ComponentModel.DataAnnotations;
namespace BTCPayServer.Models.ServerViewModels
namespace BTCPayServer.Models.ServerViewModels;
public class MaintenanceViewModel
{
public class MaintenanceViewModel
{
[Display(Name = "Change domain")]
public string DNSDomain { get; set; }
public bool CanUseSSH { get; internal set; }
}
[Display(Name = "Domain name")]
public string DNSDomain { get; set; }
public bool CanUseSSH { get; internal set; }
}

View file

@ -8,15 +8,15 @@ namespace BTCPayServer.Services
{
public class PoliciesSettings
{
[Display(Name = "Require a confirmation email for registering")]
[Display(Name = "Email confirmation required")]
public bool RequiresConfirmedEmail { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[Display(Name = "Disable new user registration on the server")]
[Display(Name = "Disable public user registration")]
public bool LockSubscription { get; set; }
[JsonIgnore]
[Display(Name = "Enable new user registration on the server")]
[Display(Name = "Enable public user registration")]
public bool EnableRegistration
{
get => !LockSubscription;
@ -24,37 +24,41 @@ namespace BTCPayServer.Services
}
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[Display(Name = "Require new users to be approved by an admin after registration")]
[Display(Name = "Admin must approve new users")]
public bool RequiresUserApproval { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
[Display(Name = "Discourage search engines from indexing this site")]
public bool DiscourageSearchEngines { get; set; }
[Display(Name = "Allow non-admins to use the internal lightning node in their stores")]
[JsonIgnore]
[Display(Name = "Search engines can index this site")]
public bool AllowSearchEngines
{
get => !DiscourageSearchEngines;
set { DiscourageSearchEngines = !value; }
}
[Display(Name = "Non-admins can use the Internal Lightning Node for their Store")]
public bool AllowLightningInternalNodeForAll { get; set; }
[Display(Name = "Allow non-admins to create hot wallets for their stores")]
[Display(Name = "Non-admins can create Hot Wallets for their Store")]
public bool AllowHotWalletForAll { get; set; }
[Display(Name = "Allow non-admins to import hot wallets for their stores")]
[Display(Name = "Non-admins can import Hot Wallets for their Store")]
public bool AllowHotWalletRPCImportForAll { get; set; }
[Display(Name = "Check releases on GitHub and notify when new BTCPay Server version is available")]
public bool CheckForNewVersions { get; set; }
[Display(Name = "Disable notifications from automatically showing (no websockets)")]
public bool DisableInstantNotifications { get; set; }
[Display(Name = "Disable stores from using the server's email settings as backup")]
public bool DisableStoresToUseServerEmailSettings { get; set; }
[JsonIgnore]
[Display(Name = "Allow stores to use the server's SMTP email settings as a default")]
public bool EnableStoresToUseServerEmailSettings
{
get => !DisableStoresToUseServerEmailSettings;
set { DisableStoresToUseServerEmailSettings = !value; }
}
[Display(Name = "Disable non-admins access to the user creation API endpoint")]
[Display(Name = "Non-admins cannot access the User Creation API Endpoint")]
public bool DisableNonAdminCreateUserApi { get; set; }
[JsonIgnore]
[Display(Name = "Non-admins can access the user creation API endpoint")]
[Display(Name = "Non-admins can access the User Creation API Endpoint")]
public bool EnableNonAdminCreateUserApi
{
get => !DisableNonAdminCreateUserApi;
@ -65,6 +69,7 @@ namespace BTCPayServer.Services
[UriAttribute]
[Display(Name = "Plugin server")]
public string PluginSource { get; set; }
[Display(Name = "Show plugins in pre-release")]
public bool PluginPreReleases { get; set; }

View file

@ -1,98 +1,96 @@
@model BTCPayServer.Models.ServerViewModels.EmailsViewModel
@model BTCPayServer.Models.EmailsViewModel
<form method="post" autocomplete="off">
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
@if (!ViewContext.ModelState.IsValid)
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
@if (!ViewContext.ModelState.IsValid)
{
<div asp-validation-summary="All"></div>
}
<div class="form-group">
<div class="d-flex flex-wrap gap-2 align-items-center justify-content-between">
<label asp-for="Settings.Server" class="form-label">SMTP Server</label>
<div class="dropdown only-for-js mt-n2" id="quick-fill">
<button class="btn btn-link p-0 dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="QuickFillDropdownToggle">
Quick Fill
</button>
<div class="dropdown-menu" aria-labelledby="QuickFillDropdownToggle">
<a class="dropdown-item" href="" data-server="smtp.gmail.com" data-port="587">Gmail.com</a>
<a class="dropdown-item" href="" data-server="mail.yahoo.com" data-port="587">Yahoo.com</a>
<a class="dropdown-item" href="" data-server="smtp.mailgun.org" data-port="587">Mailgun</a>
<a class="dropdown-item" href="" data-server="smtp.office365.com" data-port="587">Office365</a>
<a class="dropdown-item" href="" data-server="smtp.sendgrid.net" data-port="587">SendGrid</a>
</div>
</div>
</div>
<input asp-for="Settings.Server" data-fill="server" class="form-control" />
<span asp-validation-for="Settings.Server" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.Port" class="form-label"></label>
<input asp-for="Settings.Port" data-fill="port" class="form-control"/>
<span asp-validation-for="Settings.Port" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.From" class="form-label">Sender's Email Address</label>
<input asp-for="Settings.From" class="form-control" placeholder="Firstname Lastname <email@example.com>" />
<span asp-validation-for="Settings.From" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.Login" class="form-label"></label>
<input asp-for="Settings.Login" class="form-control"/>
<div class="form-text">For many email providers (like Gmail) your login is your email address.</div>
<span asp-validation-for="Settings.Login" class="text-danger"></span>
</div>
<div class="form-group">
@if (!Model.PasswordSet)
{
<div asp-validation-summary="All"></div>
<label asp-for="Settings.Password" class="form-label"></label>
<input asp-for="Settings.Password" type="password" class="form-control"/>
<span asp-validation-for="Settings.Password" class="text-danger"></span>
}
<div class="form-group">
<div class="d-flex flex-wrap gap-2 align-items-center justify-content-between">
<label asp-for="Settings.Server" class="form-label">SMTP Server</label>
<div class="dropdown only-for-js mt-n2" id="quick-fill">
<button class="btn btn-link p-0 dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="QuickFillDropdownToggle">
Quick Fill
</button>
<div class="dropdown-menu" aria-labelledby="QuickFillDropdownToggle">
<a class="dropdown-item" href="" data-server="smtp.gmail.com" data-port="587">Gmail.com</a>
<a class="dropdown-item" href="" data-server="mail.yahoo.com" data-port="587">Yahoo.com</a>
<a class="dropdown-item" href="" data-server="smtp.mailgun.org" data-port="587">Mailgun</a>
<a class="dropdown-item" href="" data-server="smtp.office365.com" data-port="587">Office365</a>
<a class="dropdown-item" href="" data-server="smtp.sendgrid.net" data-port="587">SendGrid</a>
</div>
</div>
else
{
<label asp-for="Settings.Password" class="form-label"></label>
<div class="input-group">
<input value="Configured" type="text" readonly class="form-control"/>
<button type="submit" class="btn btn-danger" name="command" value="ResetPassword" id="ResetPassword">Reset</button>
</div>
<input asp-for="Settings.Server" data-fill="server" class="form-control" />
<span asp-validation-for="Settings.Server" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.Port" class="form-label"></label>
<input asp-for="Settings.Port" data-fill="port" class="form-control"/>
<span asp-validation-for="Settings.Port" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.From" class="form-label">Sender's Email Address</label>
<input asp-for="Settings.From" class="form-control" placeholder="Firstname Lastname <email@example.com>" />
<span asp-validation-for="Settings.From" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Settings.Login" class="form-label"></label>
<input asp-for="Settings.Login" class="form-control"/>
<div class="form-text">For many email providers (like Gmail) your login is your email address.</div>
<span asp-validation-for="Settings.Login" class="text-danger"></span>
</div>
<div class="form-group">
@if (!Model.PasswordSet)
{
<label asp-for="Settings.Password" class="form-label"></label>
<input asp-for="Settings.Password" type="password" class="form-control"/>
<span asp-validation-for="Settings.Password" class="text-danger"></span>
}
else
{
<label asp-for="Settings.Password" class="form-label"></label>
<div class="input-group">
<input value="Configured" type="text" readonly class="form-control"/>
<button type="submit" class="btn btn-danger" name="command" value="ResetPassword" id="ResetPassword">Reset</button>
</div>
}
</div>
<input asp-for="PasswordSet" type="hidden"/>
<div class="my-4">
<button class="d-inline-flex align-items-center btn btn-link text-primary fw-semibold p-0" type="button" id="AdvancedSettingsButton" data-bs-toggle="collapse" data-bs-target="#AdvancedSettings" aria-expanded="false" aria-controls="AdvancedSettings">
<vc:icon symbol="caret-down"/>
<span class="ms-1">Advanced settings</span>
</button>
<div id="AdvancedSettings" class="collapse">
<div class="pt-3 pb-1">
<div class="form-group">
<div class="form-check">
<input asp-for="Settings.DisableCertificateCheck" class="form-check-input" />
<label asp-for="Settings.DisableCertificateCheck" class="form-check-label">Disable TLS certificate security checks</label>
</div>
}
</div>
<input asp-for="PasswordSet" type="hidden"/>
<div class="my-4">
<button class="d-inline-flex align-items-center btn btn-link text-primary fw-semibold p-0" type="button" id="AdvancedSettingsButton" data-bs-toggle="collapse" data-bs-target="#AdvancedSettings" aria-expanded="false" aria-controls="AdvancedSettings">
<vc:icon symbol="caret-down"/>
<span class="ms-1">Advanced settings</span>
</button>
<div id="AdvancedSettings" class="collapse">
<div class="pt-3 pb-1">
<div class="form-group">
<div class="form-check">
<input asp-for="Settings.DisableCertificateCheck" class="form-check-input" />
<label asp-for="Settings.DisableCertificateCheck" class="form-check-label">Disable TLS certificate security checks</label>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary mt-2" name="command" value="Save" id="Save">Save</button>
</div>
<button type="submit" class="btn btn-primary mt-2" name="command" value="Save" id="Save">Save</button>
</div>
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
<div class="form-group">
<h3 class="mt-5 mb-3">Testing</h3>
<p>
To test your settings, enter an email address below.
</p>
<label asp-for="TestEmail" class="form-label"></label>
<input asp-for="TestEmail" placeholder="Firstname Lastname <email@example.com>" class="form-control" />
<span asp-validation-for="TestEmail" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-secondary mt-2" name="command" value="Test" id="Test">Send Test Email</button>
</div>
<div class="row">
<div class="col-xl-10 col-xxl-constrain">
<div class="form-group">
<h3 class="mt-5 mb-3">Testing</h3>
<p>
To test your settings, enter an email address below.
</p>
<label asp-for="TestEmail" class="form-label"></label>
<input asp-for="TestEmail" placeholder="Firstname Lastname <email@example.com>" class="form-control" />
<span asp-validation-for="TestEmail" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-secondary mt-2" name="command" value="Test" id="Test">Send Test Email</button>
</div>
</form>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {

View file

@ -4,15 +4,10 @@
@inject BTCPayServer.Services.BTCPayServerEnvironment _env
@inject SignInManager<ApplicationUser> _signInManager
@inject UserManager<ApplicationUser> _userManager
@inject BTCPayServer.Services.PoliciesSettings PoliciesSettings
@{
var notificationDisabled = PoliciesSettings.DisableInstantNotifications;
if (!notificationDisabled)
{
var user = await _userManager.GetUserAsync(User);
notificationDisabled = user?.DisabledNotifications == "all";
}
var user = await _userManager.GetUserAsync(User);
var notificationDisabled = user?.DisabledNotifications == "all";
var expectedScheme = _context.HttpContext.Request.Scheme;
var expectedHost = _context.HttpContext.Request.Host.ToString().ToLower();
}

View file

@ -1,10 +1,26 @@
@model EmailsViewModel
@model ServerEmailsViewModel
@{
ViewData.SetActivePage(ServerNavPages.Emails, "Emails");
}
<h3 class="mb-4">Email Server</h3>
<partial name="EmailsBody" model="Model" />
<form method="post" autocomplete="off">
<div class="form-group" style="margin:1rem 0 2rem">
<div class="d-flex align-items-center">
<input asp-for="EnableStoresToUseServerEmailSettings" type="checkbox" class="btcpay-toggle me-3"/>
<div>
<label asp-for="EnableStoresToUseServerEmailSettings" class="form-label mb-0"></label>
<div class="text-muted">
This can be overridden at the Store level.
<a href="https://docs.btcpayserver.org/Notifications/#server-emails" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
</div>
</div>
</div>
</div>
<partial name="EmailsBody" model="Model" />
</form>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />

View file

@ -3,18 +3,17 @@
ViewData.SetActivePage(ServerNavPages.Maintenance, "Maintenance");
}
<h3 class="mb-4">@ViewData["Title"]</h3>
<h3 class="mb-3">@ViewData["Title"]</h3>
<form method="post">
<div class="row mb-5">
<div class="col-xl-8 col-xxl-constrain">
<h4 class="mb-2">Domain name</h4>
<p>You can change the domain name of your server by following <a href="https://docs.btcpayserver.org/FAQ/Deployment/#how-to-change-your-btcpay-server-domain-name" target="_blank" rel="noreferrer noopener">this guide</a>.</p>
<div class="d-flex">
<input asp-for="DNSDomain" class="form-control flex-fill" disabled="@(Model.CanUseSSH ? null : "disabled")" />
<div class="form-group">
<label asp-for="DNSDomain" class="form-label"></label>
<input asp-for="DNSDomain" class="form-control" disabled="@(Model.CanUseSSH ? null : "disabled")" />
<div class="form-text">You can change the domain name of your server by following <a href="https://docs.btcpayserver.org/FAQ/Deployment/#how-to-change-your-btcpay-server-domain-name" target="_blank" rel="noreferrer noopener">this guide</a>.</div>
<span asp-validation-for="DNSDomain" class="text-danger"></span>
<button name="command" type="submit" class="btn btn-secondary ms-3" value="changedomain" title="Change domain" disabled="@(Model.CanUseSSH ? null : "disabled")">
<button name="command" type="submit" class="btn btn-secondary mt-3" value="changedomain" title="Change domain" disabled="@(Model.CanUseSSH ? null : "disabled")">
Confirm
</button>
</div>

View file

@ -11,10 +11,11 @@
@section PageHeadContent {
<style>
input[type="checkbox"] ~ .info-note,
input[type="checkbox"] ~ .subsettings { display: none; }
input[type="checkbox"]:checked ~ .info-note { display: flex; max-width: 44em; }
input[type="checkbox"]:checked ~ .subsettings { display: block; }
input[type="checkbox"] ~ div > .info-note,
input[type="checkbox"] ~ div > .subsettings { display: none; }
input[type="checkbox"]:checked ~ div > .info-note { display: flex; max-width: 44em; }
input[type="checkbox"]:checked ~ div > .subsettings { display: block; }
.subsettings > :last-child { margin-bottom: 0 !important; }
</style>
}
@ -29,136 +30,136 @@
<div class="col-xl-10 col-xxl-constrain">
<form method="post" class="d-flex flex-column">
<div class="form-group mb-5">
<h4 class="mb-3">Registration Settings</h4>
<div class="form-check my-3">
<input asp-for="EnableRegistration" type="checkbox" class="form-check-input"/>
<label asp-for="EnableRegistration" class="form-check-label"></label>
<span asp-validation-for="EnableRegistration" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning"/>
Caution: Enabling public user registration means anyone can register to your server and may expose your BTCPay Server instance to potential security risks from unknown users.
</div>
<div class="subsettings">
<div class="form-check my-3">
@{
var emailSettings = (await _SettingsRepository.GetSettingAsync<EmailSettings>()) ?? new EmailSettings();
/* The "|| Model.RequiresConfirmedEmail" check is for the case when a user had checked
the checkbox without first configuring the e-mail settings so that they can uncheck it. */
var isEmailConfigured = emailSettings.IsComplete() || Model.RequiresConfirmedEmail;
}
<input asp-for="RequiresConfirmedEmail" type="checkbox" class="form-check-input" disabled="@(isEmailConfigured ? null : "disabled")"/>
<label asp-for="RequiresConfirmedEmail" class="form-check-label"></label>
<a href="https://docs.btcpayserver.org/FAQ/ServerSettings/#how-to-allow-registration-on-my-btcpay-server" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="RequiresConfirmedEmail" class="text-danger"></span>
@if (!isEmailConfigured)
{
<div class="mb-2">
<span class="text-secondary">Your email server has not been configured. <a asp-controller="UIServer" asp-action="Emails">Please configure it first.</a></span>
<h4 class="mb-3">Registration</h4>
<div class="d-flex gap-3">
<input asp-for="EnableRegistration" type="checkbox" class="btcpay-toggle" />
<div>
<label asp-for="EnableRegistration" class="form-label mb-0"></label>
<span asp-validation-for="EnableRegistration" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning" />
Caution: Enabling public user registration means anyone can register to your server and may expose your BTCPay Server instance to potential security risks from unknown users.
</div>
<div class="subsettings">
<div class="d-flex my-3">
@{
var emailSettings = (await _SettingsRepository.GetSettingAsync<EmailSettings>()) ?? new EmailSettings();
/* The "|| Model.RequiresConfirmedEmail" check is for the case when a user had checked
the checkbox without first configuring the e-mail settings so that they can uncheck it. */
var isEmailConfigured = emailSettings.IsComplete() || Model.RequiresConfirmedEmail;
}
<input asp-for="RequiresConfirmedEmail" type="checkbox" class="btcpay-toggle me-3" disabled="@(isEmailConfigured ? null : "disabled")" />
<div>
<label asp-for="RequiresConfirmedEmail" class="form-label mb-0"></label>
<a href="https://docs.btcpayserver.org/FAQ/ServerSettings/#how-to-allow-registration-on-my-btcpay-server" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="RequiresConfirmedEmail" class="text-danger"></span>
@if (!isEmailConfigured)
{
<div class="text-secondary">Your email server has not been configured. <a asp-controller="UIServer" asp-action="Emails">Please configure it first.</a></div>
}
</div>
</div>
<div class="d-flex my-3">
<input asp-for="RequiresUserApproval" type="checkbox" class="btcpay-toggle me-3"/>
<div>
<label asp-for="RequiresUserApproval" class="form-label mb-0"></label>
<span asp-validation-for="RequiresUserApproval" class="text-danger"></span>
</div>
</div>
<div class="d-flex my-3">
<input asp-for="EnableNonAdminCreateUserApi" type="checkbox" class="btcpay-toggle me-3"/>
<div>
<label asp-for="EnableNonAdminCreateUserApi" class="form-label mb-0"></label>
<span asp-validation-for="EnableNonAdminCreateUserApi" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning" />
Caution: Allowing non-admins to have access to API endpoints may expose your BTCPay Server instance to potential security risks from unknown users.
</div>
</div>
}
</div>
<div class="form-check my-3">
<input asp-for="RequiresUserApproval" type="checkbox" class="form-check-input"/>
<label asp-for="RequiresUserApproval" class="form-check-label"></label>
<span asp-validation-for="RequiresUserApproval" class="text-danger"></span>
</div>
<div class="form-check my-3">
<input asp-for="EnableNonAdminCreateUserApi" type="checkbox" class="form-check-input"/>
<label asp-for="EnableNonAdminCreateUserApi" class="form-check-label"></label>
<span asp-validation-for="EnableNonAdminCreateUserApi" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning"/>
Caution: Allowing non-admins to have access to API endpoints may expose your BTCPay Server instance to potential security risks from unknown users.
</div>
</div>
</div>
</div>
</div>
<div class="form-group mb-5">
<h4 class="mb-3">User Settings</h4>
<div class="form-check my-3">
<input asp-for="AllowLightningInternalNodeForAll" type="checkbox" class="form-check-input"/>
<label asp-for="AllowLightningInternalNodeForAll" class="form-check-label"></label>
<a href="https://docs.btcpayserver.org/FAQ/LightningNetwork/#how-many-users-can-use-lightning-network-in-btcpay" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="AllowLightningInternalNodeForAll" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning"/>
Caution: Enabling this option, may simplify the onboarding for third-parties but carries liabilities and security risks associated with sharing the lightning node with other users.
<div class="mb-5">
<h4 class="mb-3">Users</h4>
<div class="d-flex my-3">
<input asp-for="AllowLightningInternalNodeForAll" type="checkbox" class="btcpay-toggle me-3"/>
<div>
<label asp-for="AllowLightningInternalNodeForAll" class="form-label mb-0"></label>
<a href="https://docs.btcpayserver.org/FAQ/LightningNetwork/#how-many-users-can-use-lightning-network-in-btcpay" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="AllowLightningInternalNodeForAll" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning"/>
Caution: Enabling this option, may simplify the onboarding for third-parties but carries liabilities and security risks associated with sharing the lightning node with other users.
</div>
</div>
</div>
<div class="form-check my-3">
<input asp-for="AllowHotWalletForAll" type="checkbox" class="form-check-input"/>
<label asp-for="AllowHotWalletForAll" class="form-check-label"></label>
<a href="https://docs.btcpayserver.org/CreateWallet/#requirements-to-create-wallets" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="AllowHotWalletForAll" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning"/>
Caution: Enabling this option, may simplify the onboarding and spending for third-parties but carries liabilities and security risks associated to storing private keys of third parties on a server.
<div class="d-flex my-3">
<input asp-for="AllowHotWalletForAll" type="checkbox" class="btcpay-toggle me-3"/>
<div>
<label asp-for="AllowHotWalletForAll" class="form-label mb-0"></label>
<a href="https://docs.btcpayserver.org/CreateWallet/#requirements-to-create-wallets" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="AllowHotWalletForAll" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning"/>
Caution: Enabling this option, may simplify the onboarding and spending for third-parties but carries liabilities and security risks associated to storing private keys of third parties on a server.
</div>
</div>
</div>
<div class="form-check my-3">
<input asp-for="AllowHotWalletRPCImportForAll" type="checkbox" class="form-check-input"/>
<label asp-for="AllowHotWalletRPCImportForAll" class="form-check-label"></label>
<span asp-validation-for="AllowHotWalletRPCImportForAll" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning"/>
Caution: Enabling this option, may simplify the onboarding and spending for third-parties but carries liabilities and security risks associated to storing private keys of third parties on a server.
<div class="d-flex my-3">
<input asp-for="AllowHotWalletRPCImportForAll" type="checkbox" class="btcpay-toggle me-3"/>
<div>
<label asp-for="AllowHotWalletRPCImportForAll" class="form-label mb-0"></label>
<span asp-validation-for="AllowHotWalletRPCImportForAll" class="text-danger"></span>
<div class="info-note mt-2 text-warning" role="alert">
<vc:icon symbol="warning"/>
Caution: Enabling this option, may simplify the onboarding and spending for third-parties but carries liabilities and security risks associated to storing private keys of third parties on a server.
</div>
</div>
</div>
</div>
<div class="form-group mb-5">
<h4 class="mb-3">Email Settings</h4>
<div class="form-check my-3">
<input asp-for="EnableStoresToUseServerEmailSettings" type="checkbox" class="form-check-input"/>
<label asp-for="EnableStoresToUseServerEmailSettings" class="form-check-label"></label>
<a href="https://docs.btcpayserver.org/Notifications/#server-emails" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="EnableStoresToUseServerEmailSettings" class="text-danger"></span>
<div class="mb-5">
<h4 class="mb-3">Server</h4>
<div class="d-flex my-3">
<input asp-for="AllowSearchEngines" type="checkbox" class="btcpay-toggle me-3"/>
<div>
<label asp-for="AllowSearchEngines" class="form-label mb-0"></label>
<a href="https://docs.btcpayserver.org/FAQ/ServerSettings/#how-to-hide-my-btcpay-server-from-search-engines" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="AllowSearchEngines" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group mb-5">
<h4 class="mb-3">Notification Settings</h4>
<div class="form-check my-3">
<input asp-for="DisableInstantNotifications" type="checkbox" class="form-check-input"/>
<label asp-for="DisableInstantNotifications" class="form-check-label"></label>
<a href="https://docs.btcpayserver.org/Notifications/#notifications" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="DisableInstantNotifications" class="text-danger"></span>
</div>
</div>
<div class="form-group mb-5">
<h4 class="mb-3">Maintenance Settings</h4>
@if (ViewBag.UpdateUrlPresent)
{
<div class="form-check my-3">
<input asp-for="CheckForNewVersions" type="checkbox" class="form-check-input"/>
<label asp-for="CheckForNewVersions" class="form-check-label"></label>
<span asp-validation-for="CheckForNewVersions" class="text-danger"></span>
<div class="d-flex my-3">
<input asp-for="CheckForNewVersions" type="checkbox" class="btcpay-toggle me-3"/>
<div>
<label asp-for="CheckForNewVersions" class="form-label mb-0"></label>
<span asp-validation-for="CheckForNewVersions" class="text-danger"></span>
</div>
</div>
}
<div class="form-check my-3">
<input asp-for="DiscourageSearchEngines" type="checkbox" class="form-check-input"/>
<label asp-for="DiscourageSearchEngines" class="form-check-label"></label>
<a href="https://docs.btcpayserver.org/FAQ/ServerSettings/#how-to-hide-my-btcpay-server-from-search-engines" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
<span asp-validation-for="DiscourageSearchEngines" class="text-danger"></span>
</div>
<div class="form-check my-3">
<input asp-for="Experimental" type="checkbox" class="form-check-input"/>
<label asp-for="Experimental" class="form-check-label"></label>
<div class="d-flex align-items-center my-3">
<input asp-for="Experimental" type="checkbox" class="btcpay-toggle me-3" />
<div>
<label asp-for="Experimental" class="form-label mb-0"></label>
<div class="text-muted">
Will allow you to use the custodian account feature.
<a href="https://blog.btcpayserver.org/btcpay-server-1-9-0/#-exchange-integration-via-plugins-" target="_blank" rel="noreferrer noopener">
<vc:icon symbol="info" />
</a>
</div>
</div>
</div>
</div>
@ -168,9 +169,9 @@
<input asp-for="PluginSource" placeholder="@PoliciesSettings.DefaultPluginSource" class="form-control"/>
<span asp-validation-for="PluginSource" class="text-danger"></span>
</div>
<div class="form-check">
<input asp-for="PluginPreReleases" type="checkbox" class="form-check-input"/>
<label asp-for="PluginPreReleases" class="form-check-label"></label>
<div class="d-flex mt-n2">
<input asp-for="PluginPreReleases" type="checkbox" class="btcpay-toggle me-3"/>
<label asp-for="PluginPreReleases" class="form-label mb-0"></label>
</div>
@* To handle the multiple submit buttons on this page: Give this button
@ -179,7 +180,7 @@
<button id="SaveButton" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
</div>
<h4 class="mt-5">Customization Settings</h4>
<h4 class="mt-5">Customization</h4>
<div class="form-group mb-5">
<label asp-for="RootAppId" class="form-label"></label>
<select asp-for="RootAppId" asp-items="@(new SelectList(ViewBag.AppsList, nameof(SelectListItem.Value), nameof(SelectListItem.Text), Model.RootAppId))" class="form-select"></select>

View file

@ -1,4 +1,4 @@
@model BTCPayServer.Models.ServerViewModels.EmailsViewModel
@model BTCPayServer.Models.EmailsViewModel
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewData.SetActivePage(StoreNavPages.Emails, "Emails", Context.GetStoreData().Id);
@ -21,24 +21,27 @@
</div>
<h3 class="mb-4">Email Server</h3>
@if (Model.IsFallbackSetup())
{
<label class="d-flex align-items-center mb-4">
<input type="checkbox" id="UseCustomSMTP" checked="@hasCustomSettings" class="btcpay-toggle me-3" data-bs-toggle="collapse" data-bs-target="#SmtpSettings" aria-expanded="@hasCustomSettings" aria-controls="SmtpSettings" />
<div>
<span>Use custom SMTP settings for this store</span>
<div class="form-text">Otherwise, the server's SMTP settings will be used to send emails.</div>
</div>
</label>
<div class="checkout-settings collapse @(hasCustomSettings ? "show" : "")" id="SmtpSettings">
<form method="post" autocomplete="off">
@if (Model.IsFallbackSetup())
{
<label class="d-flex align-items-center mb-4">
<input type="checkbox" id="UseCustomSMTP" checked="@hasCustomSettings" class="btcpay-toggle me-3" data-bs-toggle="collapse" data-bs-target="#SmtpSettings" aria-expanded="@hasCustomSettings" aria-controls="SmtpSettings" />
<div>
<span>Use custom SMTP settings for this store</span>
<div class="form-text">Otherwise, the server's SMTP settings will be used to send emails.</div>
</div>
</label>
<div class="checkout-settings collapse @(hasCustomSettings ? "show" : "")" id="SmtpSettings">
<partial name="EmailsBody" model="Model" />
</div>
}
else
{
<partial name="EmailsBody" model="Model" />
</div>
}
else
{
<partial name="EmailsBody" model="Model" />
}
}
</form>
@section PageFootContent {
<partial name="_ValidationScriptsPartial" />