mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 05:54:26 +01:00
Add Server Email Rules
This commit is contained in:
@@ -3,19 +3,15 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Plugins.Emails.Views;
|
||||
using BTCPayServer.Plugins.Subscriptions.Controllers;
|
||||
using BTCPayServer.Services.Mails;
|
||||
using Dapper;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Npgsql;
|
||||
|
||||
namespace BTCPayServer.Plugins.Emails.Controllers;
|
||||
|
||||
@@ -29,28 +25,26 @@ public class UIStoreEmailRulesController(
|
||||
LinkGenerator linkGenerator,
|
||||
ApplicationDbContextFactory dbContextFactory,
|
||||
IEnumerable<EmailTriggerViewModel> triggers,
|
||||
IStringLocalizer stringLocalizer) : Controller
|
||||
IStringLocalizer stringLocalizer) : UIEmailRuleControllerBase(dbContextFactory, stringLocalizer, emailSenderFactory)
|
||||
{
|
||||
public IStringLocalizer StringLocalizer { get; set; } = stringLocalizer;
|
||||
[HttpGet("")]
|
||||
public async Task<IActionResult> StoreEmailRulesList(string storeId)
|
||||
{
|
||||
await using var ctx = dbContextFactory.CreateContext();
|
||||
var store = HttpContext.GetStoreData();
|
||||
var configured = await emailSenderFactory.IsComplete(store.Id);
|
||||
if (!configured && !TempData.HasStatusMessage())
|
||||
{
|
||||
TempData.SetStatusMessageModel(new StatusMessageModel
|
||||
{
|
||||
Severity = StatusMessageModel.StatusSeverity.Warning,
|
||||
Html = "You need to configure email settings before this feature works." +
|
||||
$" <a class='alert-link configure-email' href='{linkGenerator.GetStoreEmailSettingsLink(storeId, Request.GetRequestBaseUrl())}'>Configure store email settings</a>."
|
||||
});
|
||||
}
|
||||
public Task<IActionResult> StoreEmailRulesList(string storeId)
|
||||
=> EmailRulesListCore(CreateContext(storeId));
|
||||
|
||||
var rules = await ctx.EmailRules.GetRules(storeId).ToListAsync();
|
||||
return View("StoreEmailRulesList", rules.Select(r => new StoreEmailRuleViewModel(r, triggers)).ToList());
|
||||
}
|
||||
private EmailsRuleControllerContext CreateContext(string storeId)
|
||||
=> new()
|
||||
{
|
||||
StoreId = storeId,
|
||||
EmailSettingsLink = linkGenerator.GetStoreEmailSettingsLink(storeId, Request.GetRequestBaseUrl()),
|
||||
Rules = (ctx) => ctx.EmailRules.GetRules(storeId).ToListAsync(),
|
||||
Triggers = triggers.Where(t => !t.ServerTrigger).ToList(),
|
||||
ModifyViewModel = (vm) =>
|
||||
{
|
||||
vm.ShowCustomerEmailColumn = true;
|
||||
},
|
||||
GetRule = (ctx, ruleId) => ctx.EmailRules.GetRule(storeId, ruleId),
|
||||
RedirectToRuleList = (redirectUrl) => GoToStoreEmailRulesList(storeId, redirectUrl)
|
||||
};
|
||||
|
||||
[HttpGet("create")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
@@ -61,50 +55,13 @@ public class UIStoreEmailRulesController(
|
||||
string condition = null,
|
||||
string to = null,
|
||||
string redirectUrl = null)
|
||||
{
|
||||
return View("StoreEmailRulesManage", new StoreEmailRuleViewModel(null, triggers)
|
||||
{
|
||||
CanChangeTrigger = trigger is null,
|
||||
CanChangeCondition = offeringId is null,
|
||||
Condition = condition,
|
||||
Trigger = trigger,
|
||||
OfferingId = offeringId,
|
||||
RedirectUrl = redirectUrl,
|
||||
To = to
|
||||
});
|
||||
}
|
||||
=> EmailRulesCreateCore(CreateContext(storeId), offeringId, trigger, condition, to, redirectUrl);
|
||||
|
||||
[HttpPost("create")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public async Task<IActionResult> StoreEmailRulesCreate(string storeId, StoreEmailRuleViewModel model)
|
||||
{
|
||||
await ValidateCondition(model);
|
||||
if (!ModelState.IsValid)
|
||||
return StoreEmailRulesCreate(storeId,
|
||||
model.OfferingId,
|
||||
model.CanChangeTrigger ? null : model.Trigger);
|
||||
public Task<IActionResult> StoreEmailRulesCreate(string storeId, StoreEmailRuleViewModel model)
|
||||
=> EmailRulesCreateCore(CreateContext(storeId), model);
|
||||
|
||||
await using var ctx = dbContextFactory.CreateContext();
|
||||
var c = new EmailRuleData()
|
||||
{
|
||||
StoreId = storeId,
|
||||
Trigger = model.Trigger,
|
||||
Body = model.Body,
|
||||
Subject = model.Subject,
|
||||
Condition = string.IsNullOrWhiteSpace(model.Condition) ? null : model.Condition,
|
||||
OfferingId = model.OfferingId,
|
||||
To = model.ToAsArray()
|
||||
};
|
||||
c.SetBTCPayAdditionalData(model.AdditionalData);
|
||||
ctx.EmailRules.Add(c);
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
this.TempData.SetStatusSuccess(StringLocalizer["Email rule successfully created"]);
|
||||
return GoToStoreEmailRulesList(storeId, model);
|
||||
}
|
||||
|
||||
private IActionResult GoToStoreEmailRulesList(string storeId, StoreEmailRuleViewModel model)
|
||||
=> GoToStoreEmailRulesList(storeId, model.RedirectUrl);
|
||||
private IActionResult GoToStoreEmailRulesList(string storeId, string redirectUrl)
|
||||
{
|
||||
if (redirectUrl != null)
|
||||
@@ -114,78 +71,16 @@ public class UIStoreEmailRulesController(
|
||||
|
||||
[HttpGet("{ruleId}/edit")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public async Task<IActionResult> StoreEmailRulesEdit(string storeId, long ruleId, string redirectUrl = null)
|
||||
{
|
||||
await using var ctx = dbContextFactory.CreateContext();
|
||||
var r = await ctx.EmailRules.GetRule(storeId, ruleId);
|
||||
if (r is null)
|
||||
return NotFound();
|
||||
return View("StoreEmailRulesManage", new StoreEmailRuleViewModel(r, triggers)
|
||||
{
|
||||
CanChangeTrigger = r.OfferingId is null,
|
||||
CanChangeCondition = r.OfferingId is null,
|
||||
RedirectUrl = redirectUrl
|
||||
});
|
||||
}
|
||||
public Task<IActionResult> StoreEmailRulesEdit(string storeId, long ruleId, string redirectUrl = null)
|
||||
=> EmailRulesEditCore(CreateContext(storeId), ruleId, redirectUrl);
|
||||
|
||||
[HttpPost("{ruleId}/edit")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public async Task<IActionResult> StoreEmailRulesEdit(string storeId, long ruleId, StoreEmailRuleViewModel model)
|
||||
{
|
||||
await ValidateCondition(model);
|
||||
if (!ModelState.IsValid)
|
||||
return await StoreEmailRulesEdit(storeId, ruleId);
|
||||
|
||||
await using var ctx = dbContextFactory.CreateContext();
|
||||
var rule = await ctx.EmailRules.GetRule(storeId, ruleId);
|
||||
if (rule is null) return NotFound();
|
||||
|
||||
rule.Trigger = model.Trigger;
|
||||
rule.SetBTCPayAdditionalData(model.AdditionalData);
|
||||
rule.To = model.ToAsArray();
|
||||
rule.Subject = model.Subject;
|
||||
rule.Condition = model.Condition;
|
||||
rule.Body = model.Body;
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
this.TempData.SetStatusSuccess(StringLocalizer["Email rule successfully updated"]);
|
||||
return GoToStoreEmailRulesList(storeId, model);
|
||||
}
|
||||
|
||||
private async Task ValidateCondition(StoreEmailRuleViewModel model)
|
||||
{
|
||||
model.Condition = model.Condition?.Trim() ?? "";
|
||||
if (model.Condition.Length == 0)
|
||||
model.Condition = null;
|
||||
else
|
||||
{
|
||||
await using var ctx = dbContextFactory.CreateContext();
|
||||
try
|
||||
{
|
||||
ctx.Database
|
||||
.GetDbConnection()
|
||||
.ExecuteScalar<bool>("SELECT jsonb_path_exists('{}'::JSONB, @path::jsonpath)", new { path = model.Condition });
|
||||
}
|
||||
catch(PostgresException ex)
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.Condition), $"Invalid condition ({ex.MessageText})");
|
||||
}
|
||||
}
|
||||
}
|
||||
public Task<IActionResult> StoreEmailRulesEdit(string storeId, long ruleId, StoreEmailRuleViewModel model)
|
||||
=> EmailRulesEditCore(CreateContext(storeId), ruleId, model);
|
||||
|
||||
[HttpPost("{ruleId}/delete")]
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
public async Task<IActionResult> StoreEmailRulesDelete(string storeId, long ruleId, string redirectUrl = null)
|
||||
{
|
||||
await using var ctx = dbContextFactory.CreateContext();
|
||||
var r = await ctx.EmailRules.GetRule(storeId, ruleId);
|
||||
if (r is not null)
|
||||
{
|
||||
ctx.EmailRules.Remove(r);
|
||||
await ctx.SaveChangesAsync();
|
||||
this.TempData.SetStatusSuccess(StringLocalizer["Email rule successfully deleted"]);
|
||||
}
|
||||
|
||||
return GoToStoreEmailRulesList(storeId, redirectUrl);
|
||||
}
|
||||
public Task<IActionResult> StoreEmailRulesDelete(string storeId, long ruleId, string redirectUrl = null)
|
||||
=> EmailRulesDeleteCore(CreateContext(storeId), ruleId, redirectUrl);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user