Draft: Email signup page

This commit is contained in:
Mia Rose Winter 2024-02-08 15:44:37 +01:00
parent afdc5c7c29
commit ae8d44a59c
Signed by: miawinter
GPG key ID: 4B6F6A83178F595E
2 changed files with 85 additions and 0 deletions

View file

@ -0,0 +1,83 @@
@page "/Email/Subscribe"
@using Microsoft.Extensions.Options
@using Wave.Data
@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Identity.UI.Services
@using Microsoft.EntityFrameworkCore
@inject IOptions<Features> Features
@inject IStringLocalizer<EmailSignup> Localizer
@inject IDbContextFactory<ApplicationDbContext> ContextFactory
@inject IEmailSender EmailSender
<PageTitle>@(TitlePrefix + Localizer["Title"])</PageTitle>
@if (!string.IsNullOrWhiteSpace(Message)) {
<div class="alert alert-success">
<span>@Message</span>
</div>
}
<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 = "TitlePrefix")]
private string TitlePrefix { get; set; } = default!;
[SupplyParameterFromForm(FormName = "email-signup")]
private InputModel Model { get; set; } = new();
private string Message { get; set; } = string.Empty;
protected override void OnInitialized() {
if (Features.Value.EmailSubscriptions is not true)
throw new ApplicationException("Email subscriptions not enabled.");
}
private async Task OnValidSubmit() {
if (Features.Value.EmailSubscriptions is not true)
throw new ApplicationException("Email subscriptions not enabled.");
Message = 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
};
subscriber.Name = Model.Name;
context.Update(subscriber);
await context.SaveChangesAsync();
if (subscriber.Unsubscribed) {
await EmailSender.SendEmailAsync(subscriber.Email, Localizer["ConfirmEmailSubject"], Localizer["ConfirmEmailBody"]);
}
}
private sealed class InputModel {
[MaxLength(128)]
public string? Name { get; set; }
[EmailAddress, Required(AllowEmptyStrings = false), MaxLength(256)]
public string Email { get; set; } = string.Empty;
}
}

View file

@ -4,6 +4,7 @@
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel; using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.StaticFiles; using Microsoft.AspNetCore.StaticFiles;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -120,6 +121,7 @@
var smtpConfig = builder.Configuration.GetSection("Email:Smtp"); var smtpConfig = builder.Configuration.GetSection("Email:Smtp");
if (smtpConfig.Exists()) { if (smtpConfig.Exists()) {
builder.Services.Configure<SmtpConfiguration>(smtpConfig); builder.Services.Configure<SmtpConfiguration>(smtpConfig);
builder.Services.AddScoped<IEmailSender, SmtpEmailSender>();
builder.Services.AddScoped<IEmailSender<ApplicationUser>, SmtpEmailSender>(); builder.Services.AddScoped<IEmailSender<ApplicationUser>, SmtpEmailSender>();
} else { } else {
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>(); builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();