Add support page, admin features, and auth hardening.

Rename public affiliate route to /support with localized nav labels, and include affiliate/social/wallpaper admin, 2FA login, and related site updates.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Atakan Doğan Özban
2026-07-29 20:25:55 +02:00
co-authored by Cursor
parent 202dc16a52
commit fc45c35dbe
149 changed files with 3496 additions and 11263 deletions
+116
View File
@@ -0,0 +1,116 @@
@{
ViewBag.Title = "User Settings";
Layout = "~/Views/Shared/_AdminLayout.cshtml";
var enabled = ViewBag.TwoFactorEnabled == true;
}
<h2 class="text-white mt-3 mb-3">User Settings</h2>
<p class="text-white-50">Account: <strong class="text-white">@ViewBag.Username</strong></p>
<div class="row">
<div class="col-lg-6 mb-4">
<div class="bg-dark border border-secondary rounded p-4 text-white h-100">
<h4 class="mb-3">Change password</h4>
@if (TempData["pwdOk"] != null)
{
<div class="alert alert-success py-2">@TempData["pwdOk"]</div>
}
@if (TempData["pwdError"] != null)
{
<div class="alert alert-danger py-2">@TempData["pwdError"]</div>
}
@using (Html.BeginForm("ChangePassword", "admin", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="mb-3">
<label class="form-label">Current password</label>
<input type="password" name="currentPassword" class="form-control bg-dark text-white" autocomplete="current-password" required />
</div>
<div class="mb-3">
<label class="form-label">New password</label>
<input type="password" name="newPassword" class="form-control bg-dark text-white" autocomplete="new-password" minlength="8" required />
<small class="text-muted">At least 8 characters.</small>
</div>
<div class="mb-3">
<label class="form-label">Confirm new password</label>
<input type="password" name="confirmPassword" class="form-control bg-dark text-white" autocomplete="new-password" minlength="8" required />
</div>
<button type="submit" class="btn btn-primary">Update password</button>
}
</div>
</div>
<div class="col-lg-6 mb-4">
<div class="bg-dark border border-secondary rounded p-4 text-white h-100">
<h4 class="mb-3">
Two-factor authentication
@if (enabled)
{
<span class="badge text-bg-success ms-2">Enabled</span>
}
else
{
<span class="badge text-bg-secondary ms-2">Disabled</span>
}
</h4>
@if (TempData["tfaOk"] != null)
{
<div class="alert alert-success py-2">@TempData["tfaOk"]</div>
}
@if (TempData["tfaError"] != null)
{
<div class="alert alert-danger py-2">@TempData["tfaError"]</div>
}
@if (enabled)
{
<p class="text-white-50">2FA is active. Enter a current authenticator code to disable it.</p>
using (Html.BeginForm("DisableTwoFactor", "admin", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="mb-3">
<label class="form-label">Authenticator code</label>
<input type="text" name="code" class="form-control bg-dark text-white" maxlength="6" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" required />
</div>
<button type="submit" class="btn btn-danger" onclick="return confirm('Disable two-factor authentication?');">Disable 2FA</button>
}
}
else
{
<ol class="text-white-50">
<li>Open your authenticator app and scan the QR code below.</li>
<li>Or enter this secret manually: <code class="text-white">@ViewBag.SetupSecret</code></li>
<li>Enter the 6-digit code to confirm and enable 2FA.</li>
</ol>
<div class="text-center my-3">
<div id="totpQr" class="d-inline-block bg-white p-2 rounded"></div>
</div>
using (Html.BeginForm("EnableTwoFactor", "admin", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="mb-3">
<label class="form-label">Authenticator code</label>
<input type="text" name="code" class="form-control bg-dark text-white" maxlength="6" inputmode="numeric" pattern="[0-9]*" autocomplete="one-time-code" required />
</div>
<button type="submit" class="btn btn-success">Enable 2FA</button>
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<script>
(function () {
var uri = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject((string)ViewBag.OtpAuthUri));
var el = document.getElementById('totpQr');
if (el && uri && typeof QRCode !== 'undefined') {
new QRCode(el, { text: uri, width: 200, height: 200 });
}
})();
</script>
}
</div>
</div>
</div>