mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
Add Server Email Rules
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Plugins.Emails.Views;
|
||||
using BTCPayServer.Plugins.Emails.Views.Shared;
|
||||
using BTCPayServer.Services.Mails;
|
||||
using Dapper;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Npgsql;
|
||||
|
||||
namespace BTCPayServer.Plugins.Emails.Controllers;
|
||||
|
||||
public class UIEmailRuleControllerBase(
|
||||
ApplicationDbContextFactory dbContextFactory,
|
||||
IStringLocalizer stringLocalizer,
|
||||
EmailSenderFactory emailSenderFactory) : Controller
|
||||
{
|
||||
public class EmailsRuleControllerContext
|
||||
{
|
||||
public string? StoreId { get; set; }
|
||||
public string EmailSettingsLink { get; set; } = "";
|
||||
public List<EmailTriggerViewModel> Triggers { get; set; } = new();
|
||||
public Func<ApplicationDbContext, Task<List<EmailRuleData>>>? Rules { get; set; }
|
||||
public Action<EmailRulesListViewModel>? ModifyViewModel { get; set; }
|
||||
|
||||
public Func<ApplicationDbContext, long, Task<EmailRuleData?>>? GetRule { get; set; }
|
||||
|
||||
public Func<string?, IActionResult> RedirectToRuleList = null!;
|
||||
}
|
||||
|
||||
public ApplicationDbContextFactory DbContextFactory { get; } = dbContextFactory;
|
||||
public IStringLocalizer StringLocalizer { get; } = stringLocalizer;
|
||||
|
||||
protected async Task<IActionResult> EmailRulesListCore(EmailsRuleControllerContext emailCtx)
|
||||
{
|
||||
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='{emailCtx.EmailSettingsLink}'>Configure email settings</a>."
|
||||
});
|
||||
}
|
||||
|
||||
var rules = emailCtx.Rules is null ? new() : await emailCtx.Rules(ctx);
|
||||
var vm = new EmailRulesListViewModel()
|
||||
{
|
||||
StoreId = emailCtx.StoreId,
|
||||
ModifyPermission = Policies.CanModifyStoreSettings,
|
||||
Rules = rules.Select(r => new StoreEmailRuleViewModel(r, emailCtx.Triggers)).ToList()
|
||||
};
|
||||
if (emailCtx.ModifyViewModel is not null)
|
||||
emailCtx.ModifyViewModel(vm);
|
||||
return View("EmailRulesList", vm);
|
||||
}
|
||||
|
||||
protected IActionResult EmailRulesCreateCore(
|
||||
EmailsRuleControllerContext ctx,
|
||||
string? offeringId = null,
|
||||
string? trigger = null,
|
||||
string? condition = null,
|
||||
string? to = null,
|
||||
string? redirectUrl = null)
|
||||
{
|
||||
return View("EmailRulesManage", new StoreEmailRuleViewModel(null, ctx.Triggers)
|
||||
{
|
||||
StoreId = ctx.StoreId,
|
||||
CanChangeTrigger = trigger is null,
|
||||
CanChangeCondition = offeringId is null,
|
||||
Condition = condition,
|
||||
Trigger = trigger,
|
||||
OfferingId = offeringId,
|
||||
RedirectUrl = redirectUrl,
|
||||
To = to
|
||||
});
|
||||
}
|
||||
|
||||
protected async Task<IActionResult> EmailRulesCreateCore(
|
||||
EmailsRuleControllerContext emailCtx,
|
||||
StoreEmailRuleViewModel model)
|
||||
{
|
||||
await ValidateCondition(model);
|
||||
if (!ModelState.IsValid)
|
||||
return EmailRulesCreateCore(emailCtx,
|
||||
model.OfferingId,
|
||||
model.CanChangeTrigger ? null : model.Trigger);
|
||||
|
||||
await using var ctx = DbContextFactory.CreateContext();
|
||||
var c = new EmailRuleData()
|
||||
{
|
||||
StoreId = emailCtx.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 emailCtx.RedirectToRuleList(model.RedirectUrl);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> EmailRulesEditCore(EmailsRuleControllerContext emailCtx, long ruleId, string? redirectUrl = null)
|
||||
{
|
||||
await using var ctx = DbContextFactory.CreateContext();
|
||||
var r = emailCtx.GetRule is null ? null : await emailCtx.GetRule(ctx, ruleId);
|
||||
if (r is null)
|
||||
return NotFound();
|
||||
return View("EmailRulesManage", new StoreEmailRuleViewModel(r, emailCtx.Triggers)
|
||||
{
|
||||
OfferingId = emailCtx.StoreId,
|
||||
CanChangeTrigger = r.OfferingId is null,
|
||||
CanChangeCondition = r.OfferingId is null,
|
||||
RedirectUrl = redirectUrl
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<IActionResult> EmailRulesEditCore(EmailsRuleControllerContext emailCtx, long ruleId, StoreEmailRuleViewModel model)
|
||||
{
|
||||
await ValidateCondition(model);
|
||||
if (!ModelState.IsValid)
|
||||
return await EmailRulesEditCore(emailCtx, ruleId);
|
||||
|
||||
await using var ctx = DbContextFactory.CreateContext();
|
||||
var rule = emailCtx.GetRule is null ? null : await emailCtx.GetRule(ctx, 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 emailCtx.RedirectToRuleList(model.RedirectUrl);
|
||||
}
|
||||
|
||||
protected async Task<IActionResult> EmailRulesDeleteCore(EmailsRuleControllerContext emailCtx, long ruleId, string? redirectUrl)
|
||||
{
|
||||
await using var ctx = DbContextFactory.CreateContext();
|
||||
var r = emailCtx.GetRule is null ? null : await emailCtx.GetRule(ctx, ruleId);
|
||||
if (r is not null)
|
||||
{
|
||||
ctx.EmailRules.Remove(r);
|
||||
await ctx.SaveChangesAsync();
|
||||
this.TempData.SetStatusSuccess(StringLocalizer["Email rule successfully deleted"]);
|
||||
}
|
||||
|
||||
return emailCtx.RedirectToRuleList(redirectUrl);
|
||||
}
|
||||
|
||||
|
||||
protected 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})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user