151 lines
5.2 KiB
Plaintext
151 lines
5.2 KiB
Plaintext
@page "/Email/Subscribe"
|
|
@page "/Email/Confirm"
|
|
|
|
@using Microsoft.Extensions.Options
|
|
@using Wave.Data
|
|
@using System.ComponentModel.DataAnnotations
|
|
@using Microsoft.EntityFrameworkCore
|
|
@using Wave.Services
|
|
@using Wave.Utilities
|
|
|
|
@inject ILogger<EmailSignup> Logger
|
|
@inject IStringLocalizer<EmailSignup> Localizer
|
|
@inject IDbContextFactory<ApplicationDbContext> ContextFactory
|
|
@inject IOptions<Features> Features
|
|
@inject IEmailService EmailService
|
|
@inject EmailFactory Email
|
|
@inject IMessageDisplay Messages
|
|
@inject NavigationManager Navigation
|
|
|
|
<HeadContent>
|
|
<meta name="robots" content="nofollow">
|
|
<link rel="canonical" href="@(new UriBuilder(Navigation.BaseUri) { Scheme = "https", Port = -1, Path = "/email/subscribe" }.Uri.AbsoluteUri)" />
|
|
</HeadContent>
|
|
|
|
<PageTitle>@(Localizer["Title"] + TitlePostfix)</PageTitle>
|
|
|
|
<BoardComponent CenterContent="true">
|
|
<BoardCardComponent Heading="@Localizer["Title"]">
|
|
<EditForm method="post" FormName="email-signup" Model="Model" OnValidSubmit="OnValidSubmit">
|
|
<DataAnnotationsValidator />
|
|
|
|
<InputLabelComponent LabelText="@Localizer["Name_Label"]" For="() => Model.Name">
|
|
<InputText @bind-Value="Model.Name" class="input input-bordered w-full" autocomplete="name"
|
|
placeholder="@Localizer["Name_Placeholder"]" />
|
|
</InputLabelComponent>
|
|
<InputLabelComponent LabelText="@Localizer["Email_Label"]" For="() => Model.Name">
|
|
<InputText @bind-Value="Model.Email" class="input input-bordered w-full" autocomplete="email" type="email"
|
|
required aria-required="true" placeholder="@Localizer["Email_Placeholder"]" />
|
|
</InputLabelComponent>
|
|
|
|
<button type="submit" class="btn btn-primary w-full">@Localizer["Submit"]</button>
|
|
</EditForm>
|
|
</BoardCardComponent>
|
|
</BoardComponent>
|
|
|
|
@code {
|
|
[CascadingParameter(Name = "TitlePostfix")]
|
|
private string TitlePostfix { get; set; } = default!;
|
|
[SupplyParameterFromForm(FormName = "email-signup")]
|
|
private InputModel Model { get; set; } = new();
|
|
|
|
[Parameter, SupplyParameterFromQuery(Name = "user")]
|
|
public string? Id { get; set; }
|
|
[Parameter, SupplyParameterFromQuery(Name = "token")]
|
|
public string? Token { get; set; }
|
|
|
|
protected override async Task OnInitializedAsync() {
|
|
if (Features.Value.EmailSubscriptions is not true)
|
|
throw new ApplicationException("Email subscriptions not enabled.");
|
|
|
|
if (Id is null || Token is null) return;
|
|
try {
|
|
var id = await Email.IsTokenValid(Id, Token);
|
|
|
|
if (id is null) {
|
|
Messages.ShowError(Localizer["Failure_Message"]);
|
|
return;
|
|
}
|
|
|
|
await using var context = await ContextFactory.CreateDbContextAsync();
|
|
var subscriber = context.Set<EmailSubscriber>().IgnoreQueryFilters().FirstOrDefault(s => s.Id == id);
|
|
if (subscriber is null) {
|
|
Messages.ShowError(Localizer["Failure_Message"]);
|
|
return;
|
|
}
|
|
subscriber.Unsubscribed = false;
|
|
await context.SaveChangesAsync();
|
|
Messages.ShowSuccess(Localizer["Success_Message"]);
|
|
|
|
await Email.ClearToken(Id, Token);
|
|
|
|
var articles = await context.Set<EmailNewsletter>()
|
|
.IgnoreAutoIncludes().IgnoreQueryFilters().Where(n => n.IsSend)
|
|
.Include(a => a.Article).ThenInclude(a => a.Author)
|
|
.OrderByDescending(a => a.DistributionDateTime)
|
|
.Take(3)
|
|
.ToListAsync();
|
|
var mail = await Email.CreateWelcomeEmail(
|
|
subscriber, articles,
|
|
Localizer["WelcomeEmailSubject"],
|
|
Localizer["WelcomeEmailTitle"],
|
|
Localizer["WelcomeEmailBody"],
|
|
Localizer["WelcomeEmailBody"]);
|
|
|
|
await EmailService.ConnectAsync(CancellationToken.None);
|
|
await EmailService.SendEmailAsync(mail);
|
|
await EmailService.DisconnectAsync(CancellationToken.None);
|
|
} catch (Exception ex) {
|
|
Logger.LogError(ex, "Error trying to confirm subscriber.");
|
|
Messages.ShowError(Localizer["Failure_Message"]);
|
|
}
|
|
}
|
|
|
|
private async Task OnValidSubmit() {
|
|
if (Features.Value.EmailSubscriptions is not true)
|
|
throw new ApplicationException("Email subscriptions not enabled.");
|
|
|
|
try {
|
|
Messages.ShowSuccess(Localizer["Submit_Message"]);
|
|
await using var context = await ContextFactory.CreateDbContextAsync();
|
|
|
|
var subscriber = context.Set<EmailSubscriber>().IgnoreQueryFilters().FirstOrDefault(s => s.Email == Model.Email);
|
|
if (subscriber?.Unsubscribed is false) return;
|
|
|
|
subscriber ??= new EmailSubscriber {
|
|
Email = Model.Email.Trim(),
|
|
Unsubscribed = true,
|
|
Language = "en-US" // TODO
|
|
};
|
|
subscriber.Name = Model.Name;
|
|
subscriber.UnsubscribeReason = "Not Confirmed";
|
|
context.Update(subscriber);
|
|
await context.SaveChangesAsync();
|
|
|
|
if (subscriber.Unsubscribed) {
|
|
var email = await Email.CreateConfirmationEmail(subscriber,
|
|
Localizer["ConfirmEmailSubject"],
|
|
Localizer["ConfirmEmailTitle"],
|
|
Localizer["ConfirmEmailBody"],
|
|
Localizer["ConfirmEmailBody"],
|
|
Localizer["Submit"]);
|
|
|
|
await EmailService.ConnectAsync(CancellationToken.None);
|
|
await EmailService.SendEmailAsync(email);
|
|
await EmailService.DisconnectAsync(CancellationToken.None);
|
|
}
|
|
|
|
Model = new();
|
|
} catch (Exception ex) {
|
|
Logger.LogError(ex, "Failed to create subscriber/send confirmation mail.");
|
|
}
|
|
}
|
|
|
|
private sealed class InputModel {
|
|
[MaxLength(128)]
|
|
public string? Name { get; set; }
|
|
[EmailAddress, Required(AllowEmptyStrings = false), MaxLength(256)]
|
|
public string Email { get; set; } = string.Empty;
|
|
}
|
|
}
|