Added magic spell page

This commit is contained in:
2025-07-17 20:28:49 +08:00
parent 4e2a7ebbce
commit 651820e384
11 changed files with 254 additions and 84 deletions

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace DysonNetwork.Pass.Account;
@@ -16,4 +17,48 @@ public class MagicSpellController(AppDatabase db, MagicSpellService sp) : Contro
await sp.NotifyMagicSpell(spell, true);
return Ok();
}
[HttpGet("{spellWord}")]
public async Task<ActionResult> GetMagicSpell(string spellWord)
{
var word = Uri.UnescapeDataString(spellWord);
var spell = await db.MagicSpells
.Where(x => x.Spell == word)
.Include(x => x.Account)
.ThenInclude(x => x.Profile)
.FirstOrDefaultAsync();
if (spell is null)
return NotFound();
return Ok(spell);
}
public record class MagicSpellApplyRequest
{
public string? NewPassword { get; set; }
}
[HttpPost("{spellWord}/apply")]
public async Task<ActionResult> ApplyMagicSpell([FromRoute] string spellWord, [FromBody] MagicSpellApplyRequest request)
{
var word = Uri.UnescapeDataString(spellWord);
var spell = await db.MagicSpells
.Where(x => x.Spell == word)
.Include(x => x.Account)
.ThenInclude(x => x.Profile)
.FirstOrDefaultAsync();
if (spell is null)
return NotFound();
try
{
if (spell.Type == MagicSpellType.AuthPasswordReset && request.NewPassword is not null)
await sp.ApplyPasswordReset(spell, request.NewPassword);
else
await sp.ApplyMagicSpell(spell);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
return Ok();
}
}

View File

@@ -1,5 +1,7 @@
using System.Security.Cryptography;
using System.Text.Json;
using DysonNetwork.Pass.Email;
using DysonNetwork.Pass.Pages.Emails;
using DysonNetwork.Pass.Permission;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
@@ -12,7 +14,8 @@ public class MagicSpellService(
AppDatabase db,
IConfiguration configuration,
ILogger<MagicSpellService> logger,
IStringLocalizer<EmailResource> localizer
IStringLocalizer<EmailResource> localizer,
EmailService email
)
{
public async Task<MagicSpell> CreateMagicSpell(
@@ -79,61 +82,62 @@ public class MagicSpellService(
try
{
// switch (spell.Type)
// {
// case MagicSpellType.AccountActivation:
// await email.SendTemplatedEmailAsync<LandingEmail, LandingEmailModel>(
// contact.Account.Nick,
// contact.Content,
// localizer["EmailLandingTitle"],
// new LandingEmailModel
// {
// Name = contact.Account.Name,
// Link = link
// }
// );
// break;
// case MagicSpellType.AccountRemoval:
// await email.SendTemplatedEmailAsync<AccountDeletionEmail, AccountDeletionEmailModel>(
// contact.Account.Nick,
// contact.Content,
// localizer["EmailAccountDeletionTitle"],
// new AccountDeletionEmailModel
// {
// Name = contact.Account.Name,
// Link = link
// }
// );
// break;
// case MagicSpellType.AuthPasswordReset:
// await email.SendTemplatedEmailAsync<PasswordResetEmail, PasswordResetEmailModel>(
// contact.Account.Nick,
// contact.Content,
// localizer["EmailAccountDeletionTitle"],
// new PasswordResetEmailModel
// {
// Name = contact.Account.Name,
// Link = link
// }
// );
// break;
// case MagicSpellType.ContactVerification:
// if (spell.Meta["contact_method"] is not string contactMethod)
// throw new InvalidOperationException("Contact method is not found.");
// await email.SendTemplatedEmailAsync<ContactVerificationEmail, ContactVerificationEmailModel>(
// contact.Account.Nick,
// contactMethod!,
// localizer["EmailContactVerificationTitle"],
// new ContactVerificationEmailModel
// {
// Name = contact.Account.Name,
// Link = link
// }
// );
// break;
// default:
// throw new ArgumentOutOfRangeException();
// }
switch (spell.Type)
{
case MagicSpellType.AccountActivation:
await email.SendTemplatedEmailAsync<LandingEmail, LandingEmailModel>(
contact.Account.Nick,
contact.Content,
localizer["EmailLandingTitle"],
new LandingEmailModel
{
Name = contact.Account.Name,
Link = link
}
);
break;
case MagicSpellType.AccountRemoval:
await email.SendTemplatedEmailAsync<AccountDeletionEmail, AccountDeletionEmailModel>(
contact.Account.Nick,
contact.Content,
localizer["EmailAccountDeletionTitle"],
new AccountDeletionEmailModel
{
Name = contact.Account.Name,
Link = link
}
);
break;
case MagicSpellType.AuthPasswordReset:
await email.SendTemplatedEmailAsync<PasswordResetEmail, PasswordResetEmailModel>(
contact.Account.Nick,
contact.Content,
localizer["EmailAccountDeletionTitle"],
new PasswordResetEmailModel
{
Name = contact.Account.Name,
Link = link
}
);
break;
case MagicSpellType.ContactVerification:
if (spell.Meta["contact_method"] is not string contactMethod)
throw new InvalidOperationException("Contact method is not found.");
await email.SendTemplatedEmailAsync<ContactVerificationEmail, ContactVerificationEmailModel>(
contact.Account.Nick,
contactMethod!,
localizer["EmailContactVerificationTitle"],
new ContactVerificationEmailModel
{
Name = contact.Account.Name,
Link = link
}
);
break;
case MagicSpellType.AccountDeactivation:
default:
throw new ArgumentOutOfRangeException();
}
}
catch (Exception err)
{