Polish facelift forms and clean package warnings

This commit is contained in:
nick 2026-07-31 21:36:05 +01:00
parent 8cca5ee347
commit 9a3bf18a31
8 changed files with 249 additions and 12 deletions

View File

@ -154,7 +154,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer.Core" Version="3.0.10" /> <PackageReference Include="Humanizer.Core" Version="3.0.10" />
<PackageReference Include="MailKit" Version="4.15.1" /> <PackageReference Include="MailKit" Version="4.17.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="7.0.0" /> <PackageReference Include="Microsoft.Data.SqlClient" Version="7.0.0" />
<PackageReference Include="Microsoft.Web.Administration" Version="11.1.0" /> <PackageReference Include="Microsoft.Web.Administration" Version="11.1.0" />
<PackageReference Include="NAudio" Version="2.3.0" /> <PackageReference Include="NAudio" Version="2.3.0" />
@ -164,7 +164,6 @@
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.7" />
<PackageReference Include="SixLabors.ImageSharp.Web" Version="3.2.0" /> <PackageReference Include="SixLabors.ImageSharp.Web" Version="3.2.0" />
<PackageReference Include="System.Drawing.Common" Version="10.0.5" /> <PackageReference Include="System.Drawing.Common" Version="10.0.5" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="WebMarkupMin.AspNetCoreLatest" Version="2.21.0" /> <PackageReference Include="WebMarkupMin.AspNetCoreLatest" Version="2.21.0" />
</ItemGroup> </ItemGroup>

View File

@ -95,8 +95,15 @@ namespace CatherineLynwood.Controllers
[Route("contact-catherine")] [Route("contact-catherine")]
[HttpPost] [HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ContactCatherine(Contact contact) public async Task<IActionResult> ContactCatherine(Contact contact)
{ {
if (IsLikelySpamContact(contact))
{
_logger.LogInformation("Discarded likely spam contact submission.");
return RedirectToAction("ThankYou");
}
if (ModelState.IsValid) if (ModelState.IsValid)
{ {
await _dataAccess.SaveContact(contact, false); await _dataAccess.SaveContact(contact, false);
@ -113,6 +120,29 @@ namespace CatherineLynwood.Controllers
return View(contact); return View(contact);
} }
private bool IsLikelySpamContact(Contact contact)
{
var form = Request.HasFormContentType ? Request.Form : null;
var website = form?["Website"].ToString();
if (!string.IsNullOrWhiteSpace(website))
{
return true;
}
if (long.TryParse(form?["ContactStartedAt"].ToString(), out var startedAt))
{
var elapsedSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds() - startedAt;
if (elapsedSeconds >= 0 && elapsedSeconds < 4)
{
return true;
}
}
var message = contact.Message ?? string.Empty;
var linkCount = System.Text.RegularExpressions.Regex.Matches(message, @"https?://|www\.", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Count;
return linkCount > 2;
}
[Route("feed.xml")] [Route("feed.xml")]
[Route("rss.xml")] [Route("rss.xml")]
[Route("rss")] [Route("rss")]
@ -338,4 +368,4 @@ namespace CatherineLynwood.Controllers
#endregion Private Methods #endregion Private Methods
} }
} }

View File

@ -21,7 +21,7 @@
Birmingham-born author of gritty, emotionally truthful fiction about women, survival, family secrets, and the fire people carry after everything else has been stripped away. Birmingham-born author of gritty, emotionally truthful fiction about women, survival, family secrets, and the fire people carry after everything else has been stripped away.
</p> </p>
</div> </div>
<div class="float-md-start w-md-50 p-3"> <div class="float-md-start w-md-50 p-3 cl-about-portrait">
<figure> <figure>
<responsive-image src="catherine-lynwood-15.png" alt="Catherine Lynwood" class="img-fluid rounded-5 border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image> <responsive-image src="catherine-lynwood-15.png" alt="Catherine Lynwood" class="img-fluid rounded-5 border border-3 border-dark shadow-lg" display-width-percentage="50"></responsive-image>
<figcaption>Catherine Lynwood</figcaption> <figcaption>Catherine Lynwood</figcaption>

View File

@ -17,7 +17,13 @@
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-6"> <div class="col-md-6">
<form asp-action="ContactCatherine" method="post" onsubmit="disableSubmit(this)"> <form asp-action="ContactCatherine" method="post" onsubmit="disableSubmit(this)" class="cl-contact-form">
@Html.AntiForgeryToken()
<input type="hidden" name="ContactStartedAt" value="@DateTimeOffset.UtcNow.ToUnixTimeSeconds()" />
<div class="cl-honeypot" aria-hidden="true">
<label for="Website">Website</label>
<input id="Website" name="Website" type="text" tabindex="-1" autocomplete="off" />
</div>
<div class="col-12 col-sm-8 col-md-12"> <div class="col-12 col-sm-8 col-md-12">
<h1>Contact Catherine</h1> <h1>Contact Catherine</h1>
<p>I would love to hear your thoughts regarding my work. Please feel free to contact me and I will try my best to reply as soon as I can.</p> <p>I would love to hear your thoughts regarding my work. Please feel free to contact me and I will try my best to reply as soon as I can.</p>
@ -75,4 +81,4 @@
} }
</script> </script>
} }

View File

@ -31,8 +31,8 @@
</section> </section>
<div class="row justify-content-center p-3"> <div class="row justify-content-center p-3">
<div class="col-12 bg-white rounded-5"> <div class="col-12 bg-white rounded-5 cl-audio-panel">
<audio controls> <audio controls preload="metadata" class="w-100">
<source src="/audio/samantha-lynwood.mp3" type="audio/mpeg"> <source src="/audio/samantha-lynwood.mp3" type="audio/mpeg">
Your browser does not support the audio element. Your browser does not support the audio element.
</audio> </audio>
@ -72,4 +72,4 @@
"knowsAbout": ["fiction writing", "mystery novels", "family drama"] "knowsAbout": ["fiction writing", "mystery novels", "family drama"]
} }
</script> </script>
} }

View File

@ -43,7 +43,7 @@
} }
<form asp-action="Comment" class="row" id="comment" onsubmit="disableSubmit(this)"> <form asp-action="Comment" class="row cl-comment-form" id="comment" onsubmit="disableSubmit(this)">
<div class="col-12 pb-3"> <div class="col-12 pb-3">
<h2>Leave a Comment</h2> <h2>Leave a Comment</h2>
In invite you to leave comments regarding this blog post. As you can see I ask that you give me your name and email address, as well as your age and sex. In invite you to leave comments regarding this blog post. As you can see I ask that you give me your name and email address, as well as your age and sex.
@ -160,4 +160,4 @@
agreeCheckbox.focus(); // Focus on checkbox agreeCheckbox.focus(); // Focus on checkbox
}); });
}); });
</script> </script>

View File

@ -1687,6 +1687,208 @@ body.cl-site-shell {
border-top-color: rgba(240, 208, 160, 0.36) !important; border-top-color: rgba(240, 208, 160, 0.36) !important;
} }
/* Facelift refinement pass */
.cl-site-shell .card,
.cl-site-shell .character-card,
.cl-site-shell .accordion-item,
.cl-site-shell form.bg-white,
.cl-site-shell .modal-content,
.cl-site-shell .alert,
.cl-site-shell .bg-white,
.cl-site-shell .bg-light,
.cl-site-shell .cl-panel,
.cl-site-shell .cl-editorial-hero,
.cl-page-about section,
.cl-page-verostic section > .mb-4,
.cl-page-verostic section > .mb-5,
.cl-discovery-buy-intro,
.cl-discovery-buy-panel,
.cl-discovery-audio,
.cl-discovery-review,
.cl-discovery-chapter-grid article,
.cl-discovery-hero,
.cl-journal-filter {
border-radius: 8px !important;
border-color: rgba(240, 208, 160, 0.34) !important;
box-shadow:
0 1.35rem 3.2rem rgba(0, 0, 0, 0.44),
0 0 1.8rem rgba(201, 154, 115, 0.08),
inset 0 1px 0 rgba(255, 244, 223, 0.08),
inset 0 -1px 0 rgba(0, 0, 0, 0.26) !important;
}
.cl-site-shell .card:hover,
.cl-site-shell .cl-feature-card:hover,
.cl-discovery-chapter-grid article:hover {
border-color: rgba(240, 208, 160, 0.46) !important;
box-shadow:
0 1.55rem 3.7rem rgba(0, 0, 0, 0.5),
0 0 2.2rem rgba(201, 154, 115, 0.12),
inset 0 1px 0 rgba(255, 244, 223, 0.1),
inset 0 -1px 0 rgba(0, 0, 0, 0.28) !important;
}
.cl-site-shell .rounded-3,
.cl-site-shell .rounded-4,
.cl-site-shell .rounded-5 {
border-radius: 8px !important;
}
.cl-page-journal .pagination {
gap: 0.28rem;
flex-wrap: wrap;
}
.cl-page-journal .page-link {
min-width: 2.05rem;
color: #fff1d8 !important;
text-align: center;
background:
linear-gradient(145deg, rgba(84, 42, 31, 0.96), rgba(40, 19, 20, 0.96)) !important;
border: 1px solid rgba(240, 208, 160, 0.36) !important;
border-radius: 7px !important;
box-shadow: inset 0 1px 0 rgba(255, 244, 223, 0.08), 0 0.45rem 1rem rgba(0, 0, 0, 0.25);
}
.cl-page-journal .page-link:hover,
.cl-page-journal .page-link:focus {
color: #fff7ec !important;
background:
linear-gradient(145deg, rgba(123, 41, 67, 0.98), rgba(70, 28, 43, 0.98)) !important;
}
.cl-page-journal .page-item.active .page-link {
color: #24120f !important;
background: linear-gradient(145deg, #f0d0a0, #c99a73) !important;
border-color: rgba(255, 243, 223, 0.62) !important;
font-weight: 800;
}
.cl-page-journal .page-item.disabled .page-link {
color: rgba(240, 208, 160, 0.48) !important;
background: rgba(26, 13, 13, 0.72) !important;
}
.cl-about-portrait {
position: relative;
z-index: 3;
}
.cl-about-portrait figure {
margin: 0;
padding: 0.7rem;
background:
linear-gradient(145deg, rgba(255, 232, 194, 0.14), rgba(75, 24, 39, 0.12)),
rgba(18, 10, 10, 0.72);
border: 1px solid rgba(240, 208, 160, 0.34);
border-radius: 8px;
box-shadow: 0 1.5rem 3.5rem rgba(0, 0, 0, 0.48), 0 0 2rem rgba(201, 154, 115, 0.12);
}
.cl-about-portrait .img-fluid {
filter: none !important;
opacity: 1 !important;
}
.cl-about-portrait figcaption {
margin-top: 0.55rem;
color: rgba(240, 208, 160, 0.82);
text-align: center;
}
.cl-contact-form {
padding: clamp(1rem, 3vw, 2rem);
background:
linear-gradient(145deg, rgba(255, 233, 197, 0.11), rgba(79, 28, 42, 0.08)),
rgba(21, 13, 13, 0.68);
border: 1px solid rgba(240, 208, 160, 0.28);
border-radius: 8px;
box-shadow: 0 1.4rem 3.4rem rgba(0, 0, 0, 0.42), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.cl-contact-form .form-floating > label {
color: #5c3a25 !important;
font-weight: 650;
}
.cl-contact-form .form-control {
color: #2a1812;
background: linear-gradient(145deg, #f7ead5, #e5cda8);
border-color: rgba(240, 208, 160, 0.42);
}
.cl-contact-form .form-control:focus {
color: #21100d;
background: #fff1d8;
}
.cl-comment-form {
padding: clamp(1rem, 3vw, 2rem);
background:
linear-gradient(145deg, rgba(255, 233, 197, 0.11), rgba(79, 28, 42, 0.08)),
rgba(21, 13, 13, 0.68);
border: 1px solid rgba(240, 208, 160, 0.28);
border-radius: 8px;
box-shadow: 0 1.4rem 3.4rem rgba(0, 0, 0, 0.42), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.cl-comment-form .form-floating > label,
.cl-comment-form .form-check-label {
color: #5c3a25 !important;
font-weight: 650;
}
.cl-comment-form .form-control,
.cl-comment-form .form-select {
color: #2a1812;
background: linear-gradient(145deg, #f7ead5, #e5cda8);
border-color: rgba(240, 208, 160, 0.42);
}
.cl-comment-form .form-control:focus,
.cl-comment-form .form-select:focus {
color: #21100d;
background: #fff1d8;
}
.cl-comment-form .alert .form-check-label {
color: #fff0d9 !important;
}
.cl-honeypot {
position: absolute;
left: -10000px;
width: 1px;
height: 1px;
overflow: hidden;
}
.cl-audio-panel,
.audio-player,
.cl-site-shell .plyr--audio {
padding: 0.75rem;
background:
linear-gradient(145deg, rgba(255, 233, 197, 0.12), rgba(92, 32, 63, 0.12)),
rgba(21, 13, 13, 0.78) !important;
border: 1px solid rgba(240, 208, 160, 0.32);
border-radius: 8px;
box-shadow: 0 1rem 2.4rem rgba(0, 0, 0, 0.34), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.cl-site-shell audio {
display: block;
width: 100%;
min-height: 46px;
filter: sepia(0.12) saturate(0.82) brightness(0.95);
}
.cl-site-shell .plyr--audio .plyr__controls {
color: #2a1812 !important;
background: linear-gradient(145deg, #fff1d8, #d7b982) !important;
border: 1px solid rgba(240, 208, 160, 0.45) !important;
border-radius: 7px !important;
}
@media (max-width: 991.98px) { @media (max-width: 991.98px) {
.cl-discovery-hero, .cl-discovery-hero,
.cl-discovery-buy-shell, .cl-discovery-buy-shell,

File diff suppressed because one or more lines are too long