btcpayserver/BTCPayServer/Controllers/GreenField/GreenfieldStoreEmailController.cs
rockstardev a7e3cbb105
Adding endpoint to set server email settings (#6601)
* Adding endpoint in Greenfield to allow server email settings

* Adding related swagger file

* Refactoring EmailSettingsData to be more readable

* Adding server email masking

* Adding tests

* Update BTCPayServer/wwwroot/swagger/v1/swagger.template.serveremail.json

Co-authored-by: d11n <mail@dennisreimann.de>

* Masking smtp server email returned over greenfield api and test

* Retaining password if password mask is used

* Remove magic string *****

* Flatten request for server's settings. Fix bug on shared setting instances

* Remove useless doc

* Simplify code

* Fix Store Email settings page

---------

Co-authored-by: d11n <mail@dennisreimann.de>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2025-02-27 15:59:17 +09:00

106 lines
4.2 KiB
C#

#nullable enable
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
using BTCPayServer.Services.Mails;
using BTCPayServer.Services.Stores;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
namespace BTCPayServer.Controllers.GreenField
{
[ApiController]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[EnableCors(CorsPolicies.All)]
public class GreenfieldStoreEmailController : Controller
{
private readonly EmailSenderFactory _emailSenderFactory;
private readonly StoreRepository _storeRepository;
public GreenfieldStoreEmailController(EmailSenderFactory emailSenderFactory, StoreRepository storeRepository)
{
_emailSenderFactory = emailSenderFactory;
_storeRepository = storeRepository;
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/stores/{storeId}/email/send")]
public async Task<IActionResult> SendEmailFromStore(string storeId,
[FromBody] SendEmailRequest request)
{
var store = HttpContext.GetStoreData();
if (store == null)
{
return this.CreateAPIError(404, "store-not-found", "The store was not found");
}
if (!MailboxAddressValidator.TryParse(request.Email, out var to))
{
ModelState.AddModelError(nameof(request.Email), "Invalid email");
return this.CreateValidationError(ModelState);
}
var emailSender = await _emailSenderFactory.GetEmailSender(storeId);
if (emailSender is null)
{
return this.CreateAPIError(404, "smtp-not-configured", "Store does not have an SMTP server configured.");
}
emailSender.SendEmail(to, request.Subject, request.Body);
return Ok();
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/email")]
public IActionResult GetStoreEmailSettings()
{
var store = HttpContext.GetStoreData();
return store == null ? StoreNotFound() : Ok(FromModel(store));
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPut("~/api/v1/stores/{storeId}/email")]
public async Task<IActionResult> UpdateStoreEmailSettings(string storeId, EmailSettings request)
{
var store = HttpContext.GetStoreData();
if (store == null)
{
return StoreNotFound();
}
if (!string.IsNullOrEmpty(request.From) && !MailboxAddressValidator.IsMailboxAddress(request.From))
{
request.AddModelError(e => e.From,
"Invalid email address", this);
return this.CreateValidationError(ModelState);
}
var blob = store.GetStoreBlob();
// retaining the password if it exists and was not provided in request
if (string.IsNullOrEmpty(request.Password) && blob.EmailSettings?.Password != null)
request.Password = blob.EmailSettings?.Password;
blob.EmailSettings = request;
if (store.SetStoreBlob(blob))
{
await _storeRepository.UpdateStore(store);
}
return Ok(FromModel(store));
}
private EmailSettings FromModel(Data.StoreData data)
{
var emailSettings = data.GetStoreBlob().EmailSettings;
if (emailSettings == null)
return new EmailSettings();
emailSettings.Password = null;
return emailSettings;
}
private IActionResult StoreNotFound()
{
return this.CreateAPIError(404, "store-not-found", "The store was not found");
}
}
}