💄 Restyled web pages

This commit is contained in:
2025-07-10 01:53:44 +08:00
parent 08b5ffa02f
commit ed2961a5d5
16 changed files with 2758 additions and 1332 deletions

View File

@ -4,10 +4,10 @@
ViewData["Title"] = "Authorize Application";
}
<div class="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900 transition-colors duration-200 py-12 px-4 sm:px-6 lg:px-8">
<div class="max-w-md w-full space-y-8 bg-white dark:bg-gray-800 p-8 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 transition-colors duration-200">
<div class="text-center">
<h2 class="mt-6 text-3xl font-extrabold text-gray-900 dark:text-white">
<div class="min-h-screen flex items-center justify-center bg-base-200 py-12 px-4 sm:px-6 lg:px-8">
<div class="card w-full max-w-md bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title justify-center text-2xl font-bold">
Authorize Application
</h2>
@if (!string.IsNullOrEmpty(Model.AppName))
@ -16,21 +16,17 @@
<div class="flex items-center justify-center">
@if (!string.IsNullOrEmpty(Model.AppLogo))
{
<div class="relative h-16 w-16 flex-shrink-0">
<img class="h-16 w-16 rounded-lg object-cover border border-gray-200 dark:border-gray-700"
src="@Model.AppLogo"
alt="@Model.AppName logo"
onerror="this.onerror=null; this.src='data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzczz0idy02IGgtNiB0ZXh0LWdyYXktNDAwIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xOS42MDMgMy4wMDRjMS4xNTMgMCAyLjI2LjE4IDMuMzI5LjUxM2EuNzUuNzUgMCAwMS0uMzI4IDEuNDQ1IDE2LjkzIDE2LjkzIDAgMDAtNi4wMS0xuMTAzLjc1Ljc1IDAgMDEtLjY2OC0uNzQ4VjMuNzVBLjc1Ljc1IDAgMDExNi41IDNoMy4xMDN6TTMxLjUgMjEuMDA4Yy0uU0UuNzUgNzUuNzUgMCAwMTEuOTQ4LjA1MWMuMDgxLjkxOC4wNTIgMS44MzgtLjA4NiAyLjczNGEuNzUuNzUgMCAwMS0xLjQ5LS4xNTkgMjEuMzg2IDIxLjM4NiAwIDAwLjA2LTIuNTc1Ljc1Ljc1IDAgMDExLjU3OC0uMDQzem0tMy4wMi0xOC4wMmMuMDYgMS4wOTIuMDQgMi4xODctLjA1NiAzLjI3MmEuNzUuNzUgMCAwMS0xLjQ5Mi0uMTY0Yy4wOTItLjg3NC4xMDctMS43NTYuMDUxLTIuNjA3YS43NS43NSAwIDAxMS40OTctLjEwMXpNNS42MzcgNS42MzJjLS4zMzQuMS0uNjc2LjE4NS0xLjAyNi4yNTdhLjc1Ljc1IDAgMDEuMTQ5LTEuNDljLjQyNS0uMDg1Ljg1Mi0uMTg5IDEuMjY4LS4zMDRhLjc1Ljc1IDAgMDEuMzYgMS40Mzd6TTMuMzMgMTkuNjUzYy0uMTY1LS4zNS0uMzA4LS43MDctNDIuNjUzLjc1Ljc1IDAgMS4zODgtLjU0MiAxLjQ5LTEuMjg1LjA0Ni0uMzI2LjEwNi0uNjUyLjE4LS45NzZhLjc1Ljc1IDAgMTExLjQ2LS41M2MuMTA2LjQzNy4xODkuODgxLjI0NSAxLjM0OGEuNzUuNzUgMCAwMS0xLjQ5LjIzM3pNTEuMzUzIDIuNzY3YS43NS43NSAwIDAxLjc1LS4wMTdsLjAwMS4wMDFoLjAwMWwuMDAyLjAwMWwuMDA3LjAwM2wuMDI0LjAxM2MuMDIuMDEuMDQ1LjAyNS4wNzkuMDQ2LjA2Ny4wNDIuMTYxLjEwMi4yNzUuMTc4LjIzMi4xNTEuNTUuMzgzLjg1Ni42NjdsLjAyNy4wMjRjLjYxNi41NTggMS4yMTIgMS4xNzYgMS43MzMgMS44NDNhLjc1Ljc1IDAgMDEtMS4yNC44N2MtLjQ3LS42NzEtMS4wMzEtMS4yOTItMS42LFsxLjYxNi0xLjYxNmEzLjc1IDMuNzUgMCAwMC01LjMwNS01LjMwNGwtMS4wNi0xuMDZBNy4yNDMgNy4yNDMgMCAwMTUxLjM1MyAyLjc2N3pNNDQuMzc5IDkuNjRsLTEuNTYgMS41NmE2Ljk5IDYuOTkgMCAwMTIuMjMgNC4zMzcgNi45OSA2Ljk5IDAgMDEtMi4yMyA1LjE3NmwtMS41Ni0xLjU2QTguNDkgOC40OSAwIDAwNDUuNSAxNS41YzAtMi4yOTYtLjg3NC00LjQzLTIuMTIxLTYuMDF6bS0zLjUzLTMuNTNsLTEuMDYxLTEuMDZhNy4yNDMgNy4yNDMgMCAwMTkuMTkyIDkuE2x0LTEuMDYgMS4wNjFhNS43NDkgNS43NDkgMCAwMC04LjEzLTguMTN6TTM0LjUgMTUuNWE4Ljk5IDguOTkgMCAwMC0yLjYzMSA2LjM2OS43NS43NSAwIDExLTEuNDk0LS43MzlDNzIuMzkgMjAuMDYgMzMuNSAxNy41NzUgMzMuNSAxNS41YzAtMi4zNzYgMS4wOTktNC40MzggMi44MTEtNS44MTJsLS4zOTYtLjM5NmEuNzUuNzUgMCAwMTEuMDYtMS4wNkwzNy41IDkuNDRWMmgtL4wMDJhLjc1Ljc1IDAgMDEtLjc0OC0uNzVWMS41YS43NS43NSAwIDAxLjc1LS43NWg2YS43NS43NSAwIDAxLjc1Ljc1di4yNWEwIC43NS0uNzUuNzVoLS4wMDF2Ny40NGwzLjUzNy0zLjUzN2EuNzUuNzUgMCAwMTEuMDYgMS4wNmwtLjM5Ni4zOTZDMzUuNDAxIDExLjA2MiAzNC41IDEzLjEyNCAzNC41IDE1LjV6TTM5IDIuMjV2Ni4wMy0uMDAyYTEuNSAxLjUgMCAwMS0uNDQ0IDEuMDZsLTEuMDYxIDEuMDZBOC40OSA4LjQ5IDAgMDAzOSAxNS41YzAgMi4yOTYtLjg3NCA0LjQzLTIuMTIxIDYuMDFsMS41NiAxLjU2QTYuOTkgNi45OSAwIDAwNDIgMTUuNWE2Ljk5IDYuOTkgMCAwMC0yLjIzLTUuMTc2bC0xLjU2LTEuNTZhMS41IDEuNSAwIDAxLS40NC0xLjA2VjIuMjVoLTF6TTI0IDkuNzVhLjc1Ljc1IDAgMDEtLjc1Ljc1di0uNWMwLS40MTQuMzM2LS43NS43NS0uNzVoLjVjLjQxNCAwIC43NS4zMzYuNzUuNzV2LjVhLjc1Ljc1IDAgMDEtLjc1Ljc1aC0uNXpNMTkuNSAxM2EuNzUuNzUgMCAwMS0uNzUtLjc1di0uNWMwLS40MTQuMzM2LS43NS43NS0uNzVoLjVjLjQxNCAwIC43NS4zMzYuNzUuNzV2LjVhLjc1Ljc1IDAgMDEtLjc1Ljc1aC0uNXpNMTUgMTYuMjVhLjc1Ljc1IDAgMDEuNzUtLjc1aC41Yy40MTQgMCAuNzUuMzM2Ljc1Ljc1di41YS43NS43NSAwIDAxLS43NS43NWgtLjVhLjc1Ljc1IDAgMDEtLjc1LS43NXYtLjV6IiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=';">
<div class="absolute inset-0 flex items-center justify-center bg-gray-100 dark:bg-gray-700 rounded-lg border border-gray-200 dark:border-gray-600">
<span class="text-xs font-medium text-gray-500 dark:text-gray-300">@Model.AppName?[0]</span>
<div class="avatar">
<div class="w-16 rounded">
<img src="@Model.AppLogo" alt="@Model.AppName logo" />
</div>
</div>
}
<div class="ml-4 text-left">
<h3 class="text-lg font-medium text-gray-900 dark:text-white">@Model.AppName</h3>
<h3 class="text-lg font-medium">@Model.AppName</h3>
@if (!string.IsNullOrEmpty(Model.AppUri))
{
<a href="@Model.AppUri" class="text-sm text-blue-600 dark:text-blue-400 hover:text-blue-500 dark:hover:text-blue-300 transition-colors duration-200" target="_blank" rel="noopener noreferrer">
<a href="@Model.AppUri" class="text-sm link link-primary" target="_blank" rel="noopener noreferrer">
@Model.AppUri
</a>
}
@ -38,77 +34,69 @@
</div>
</div>
}
<p class="mt-6 text-sm text-gray-600 dark:text-gray-300">
<p class="mt-6 text-sm text-center">
wants to access your account with the following permissions:
</p>
</div>
<div class="mt-6">
<ul class="border border-gray-200 dark:border-gray-700 rounded-lg divide-y divide-gray-200 dark:divide-gray-700 overflow-hidden">
@if (Model.Scope != null)
{
var scopeDescriptions = new Dictionary<string, (string Name, string Description)>
<div class="mt-6">
<ul class="menu bg-base-200 rounded-box">
@if (Model.Scope != null)
{
["openid"] = ("OpenID", "Read your basic profile information"),
["profile"] = ("Profile", "View your basic profile information"),
["email"] = ("Email", "View your email address"),
["offline_access"] = ("Offline Access", "Access your data while you're not using the application")
};
var scopeDescriptions = new Dictionary<string, (string Name, string Description)>
{
["openid"] = ("OpenID", "Read your basic profile information"),
["profile"] = ("Profile", "View your basic profile information"),
["email"] = ("Email", "View your email address"),
["offline_access"] = ("Offline Access", "Access your data while you're not using the application")
};
foreach (var scope in Model.Scope.Split(' ').Where(s => !string.IsNullOrWhiteSpace(s)))
{
var scopeInfo = scopeDescriptions.GetValueOrDefault(scope, (scope, scope.Replace('_', ' ')));
<li class="px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-150">
<div class="flex items-start">
<div class="flex-shrink-0 pt-0.5">
<svg class="h-5 w-5 text-green-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
foreach (var scope in Model.Scope.Split(' ').Where(s => !string.IsNullOrWhiteSpace(s)))
{
var scopeInfo = scopeDescriptions.GetValueOrDefault(scope, (scope, scope.Replace('_', ' ')));
<li>
<a>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-success" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<p class="text-sm font-medium text-gray-900 dark:text-white">@scopeInfo.Item1</p>
<p class="text-xs text-gray-500 dark:text-gray-400">@scopeInfo.Item2</p>
</div>
</div>
</li>
<div>
<p class="font-medium">@scopeInfo.Item1</p>
<p class="text-xs text-base-content/70">@scopeInfo.Item2</p>
</div>
</a>
</li>
}
}
}
</ul>
<div class="mt-4 text-xs text-gray-500 dark:text-gray-400">
<p>By authorizing, you allow this application to access your information on your behalf.</p>
</ul>
<div class="mt-4 text-xs text-base-content/70">
<p>By authorizing, you allow this application to access your information on your behalf.</p>
</div>
</div>
</div>
<form method="post" class="mt-8 space-y-4">
<input type="hidden" asp-for="ClientIdString" />
<input type="hidden" asp-for="ResponseType" name="response_type" />
<input type="hidden" asp-for="RedirectUri" name="redirect_uri" />
<input type="hidden" asp-for="Scope" name="scope" />
<input type="hidden" asp-for="State" name="state" />
<input type="hidden" asp-for="Nonce" name="nonce" />
<input type="hidden" asp-for="ReturnUrl" name="returnUrl" />
<input type="hidden" name="code_challenge" value="@HttpContext.Request.Query["code_challenge"]" />
<input type="hidden" name="code_challenge_method" value="@HttpContext.Request.Query["code_challenge_method"]" />
<input type="hidden" name="response_mode" value="@HttpContext.Request.Query["response_mode"]" />
<div class="flex flex-col space-y-3">
<button type="submit" name="allow" value="true"
class="w-full flex justify-center py-2.5 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:focus:ring-offset-gray-800 transition-colors duration-200">
Allow
</button>
<button type="submit" name="allow" value="false"
class="w-full flex justify-center py-2.5 px-4 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:focus:ring-offset-gray-800 transition-colors duration-200">
Deny
</button>
</div>
<div class="mt-4 pt-4 border-t border-gray-200 dark:border-gray-700">
<p class="text-xs text-center text-gray-500 dark:text-gray-400">
You can change these permissions later in your account settings.
</p>
</div>
</form>
<form method="post" class="mt-8 space-y-4">
<input type="hidden" asp-for="ClientIdString" />
<input type="hidden" asp-for="ResponseType" name="response_type" />
<input type="hidden" asp-for="RedirectUri" name="redirect_uri" />
<input type="hidden" asp-for="Scope" name="scope" />
<input type="hidden" asp-for="State" name="state" />
<input type="hidden" asp-for="Nonce" name="nonce" />
<input type="hidden" asp-for="ReturnUrl" name="returnUrl" />
<input type="hidden" name="code_challenge" value="@HttpContext.Request.Query["code_challenge"]" />
<input type="hidden" name="code_challenge_method" value="@HttpContext.Request.Query["code_challenge_method"]" />
<input type="hidden" name="response_mode" value="@HttpContext.Request.Query["response_mode"]" />
<div class="card-actions justify-center">
<button type="submit" name="allow" value="true" class="btn btn-primary">Allow</button>
<button type="submit" name="allow" value="false" class="btn btn-ghost">Deny</button>
</div>
<div class="mt-4 pt-4 border-t border-base-300">
<p class="text-xs text-center text-base-content/70">
You can change these permissions later in your account settings.
</p>
</div>
</form>
</div>
</div>
</div>
@ -124,4 +112,4 @@
_ => scope
};
}
}
}

View File

@ -5,10 +5,12 @@
Layout = "_Layout";
}
<div class="h-full flex items-center justify-center">
<div class="max-w-lg w-full mx-auto p-6 text-center">
<h1 class="text-2xl font-bold text-gray-900 dark:text-white">Authentication Successful</h1>
<p class="mb-6 text-gray-900 dark:text-white">You can now close this window and return to the application.</p>
<div class="hero min-h-full bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<h1 class="text-5xl font-bold">Authentication Successful</h1>
<p class="py-6">You can now close this window and return to the application.</p>
</div>
</div>
</div>
@ -44,4 +46,4 @@
}
})();
</script>
}
}

View File

@ -6,8 +6,11 @@
Response.Redirect($"/web/auth/challenge/{Model.Id}/select-factor");
}
<div class="h-full flex items-center justify-center bg-gray-100 dark:bg-gray-900">
<div class="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-md w-full max-w-md text-center">
<p>Redirecting to authentication page...</p>
<div class="hero min-h-full bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<span class="loading loading-spinner loading-lg"></span>
<p class="py-6">Redirecting to authentication page...</p>
</div>
</div>
</div>
</div>

View File

@ -5,32 +5,32 @@
var returnUrl = Model.ReturnUrl ?? "";
}
<div class="h-full flex items-center justify-center bg-gray-100 dark:bg-gray-900">
<div class="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-md w-full max-w-md">
<h1 class="text-2xl font-bold text-center text-gray-900 dark:text-white mb-6">Login</h1>
<form method="post">
<input type="hidden" asp-for="ReturnUrl" value="@returnUrl" />
<div class="mb-4">
<label asp-for="Username"
class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"></label>
<input asp-for="Username"
class="form-input mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-500 focus:ring-opacity-50 dark:bg-gray-700 dark:border-gray-600 dark:text-white px-4 py-2"/>
<span asp-validation-for="Username" class="text-red-500 text-sm mt-1"></span>
<div class="hero min-h-full bg-base-200">
<div class="hero-content w-full max-w-md">
<div class="card w-full bg-base-100 shadow-xl">
<div class="card-body px-8 py-7">
<h1 class="card-title justify-center text-2xl font-bold">Welcome back!</h1>
<p class="text-center">Login to your Solar Network account to continue.</p>
<form method="post" class="mt-4">
<input type="hidden" asp-for="ReturnUrl" value="@returnUrl"/>
<div class="form-control">
<label class="label" asp-for="Username">
<span class="label-text">Username</span>
</label>
<input asp-for="Username" class="input input-bordered w-full"/>
<span asp-validation-for="Username" class="text-error text-sm mt-1"></span>
</div>
<div class="form-control mt-6">
<button type="submit" class="btn btn-primary w-full">Next</button>
</div>
<div class="text-sm text-center mt-4">
<span class="text-base-content/70">Have no account?</span> <br/>
<a href="https://solian.app/#/auth/create-account" class="link link-primary">
Create a new account →
</a>
</div>
</form>
</div>
<button type="submit"
class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">
Next
</button>
</form>
<div class="mt-8 flex flex-col text-sm text-center">
<span class="text-gray-900 dark:text-white opacity-80">Have no account?</span>
<a href="https://solian.app/#/auth/create-account"
class="text-blue-600 hover:text-blue-500 dark:text-blue-400 dark:hover:text-blue-300">
Create a new account →
</a>
</div>
</div>
</div>

View File

@ -5,54 +5,92 @@
ViewData["Title"] = "Select Authentication Method";
}
<div class="h-full flex items-center justify-center bg-gray-100 dark:bg-gray-900">
<div class="bg-white dark:bg-gray-800 p-8 rounded-lg shadow-md w-full max-w-md">
<h1 class="text-2xl font-bold text-center text-gray-900 dark:text-white mb-6">Select Authentication Method</h1>
<div class="hero min-h-full bg-base-200">
<div class="hero-content w-full max-w-md">
<div class="card w-full bg-base-100 shadow-xl">
<div class="card-body">
<h1 class="card-title justify-center text-2xl font-bold">Select Authentication Method</h1>
@if (Model.AuthChallenge == null)
{
<p class="text-red-500 text-center">Challenge not found or expired.</p>
}
else if (Model.AuthChallenge.StepRemain == 0)
{
<p class="text-green-600 dark:text-green-400 text-center">Challenge completed. Redirecting...</p>
}
else
{
<p class="text-gray-700 dark:text-gray-300 mb-4">Please select an authentication method:</p>
<div class="space-y-4">
@foreach (var factor in Model.AuthFactors)
@if (Model.AuthChallenge == null)
{
<div class="mb-4">
<form method="post" asp-page-handler="SelectFactor" class="w-full" id="factor-@factor.Id">
<input type="hidden" name="SelectedFactorId" value="@factor.Id"/>
@if (factor.Type == AccountAuthFactorType.EmailCode)
{
<div class="mb-3">
<label for="hint-@factor.Id" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Email to send code to
</label>
<input type="email"
id="hint-@factor.Id"
name="hint"
class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:text-white"
placeholder="Enter your email"
required>
</div>
}
<button type="submit"
class="w-full text-left p-4 bg-gray-50 dark:bg-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 rounded-lg transition-colors">
<div class="font-medium text-gray-900 dark:text-white">@GetFactorDisplayName(factor.Type)</div>
<div class="text-sm text-gray-500 dark:text-gray-400">@GetFactorDescription(factor.Type)</div>
</button>
</form>
<div class="alert alert-error">
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<span>Challenge not found or expired.</span>
</div>
}
else if (Model.AuthChallenge.StepRemain == 0)
{
<div class="alert alert-success">
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none"
viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
<span>Challenge completed. Redirecting...</span>
</div>
}
else
{
<p class="text-center">Please select an authentication method:</p>
<div class="space-y-4">
@foreach (var factor in Model.AuthFactors)
{
<form method="post" asp-page-handler="SelectFactor" class="w-full" id="factor-@factor.Id">
<input type="hidden" name="SelectedFactorId" value="@factor.Id"/>
@if (factor.Type == AccountAuthFactorType.EmailCode)
{
<div class="card w-full bg-base-200 card-sm shadow-sm rounded-md">
<div class="py-4 px-5 align-items-center">
<div>
<h2 class="card-title">@GetFactorDisplayName(factor.Type)</h2>
<p>@GetFactorDescription(factor.Type)</p>
</div>
<div class="join w-full mt-2">
<div class="flex-1">
<label class="input join-item input-sm">
<input id="hint-@factor.Id" type="email"
placeholder="mail@site.com" required/>
</label>
</div>
<button class="btn btn-primary join-item btn-sm">
<span class="material-symbols-outlined">
arrow_right_alt
</span>
</button>
</div>
</div>
</div>
}
else
{
<div class="card w-full bg-base-200 card-sm shadow-sm rounded-md">
<div class="flex py-4 px-5 align-items-center">
<div class="flex-1">
<h2 class="card-title">@GetFactorDisplayName(factor.Type)</h2>
<p>@GetFactorDescription(factor.Type)</p>
</div>
<div class="justify-end card-actions">
<button type="submit" class="btn btn-primary btn-sm">
<span class="material-symbols-outlined">
arrow_right_alt
</span>
</button>
</div>
</div>
</div>
}
</form>
}
</div>
}
</div>
}
</div>
</div>
</div>
@ -78,4 +116,4 @@
_ => string.Empty
};
}
}

View File

@ -5,73 +5,82 @@
ViewData["Title"] = "Verify Your Identity";
}
<div class="h-full flex items-center justify-center bg-gray-100 dark:bg-gray-900">
<div class="bg-white dark:bg-gray-800 px-8 pt-8 pb-4 rounded-lg shadow-md w-full max-w-md">
<h1 class="text-2xl font-bold text-center text-gray-900 dark:text-white mb-2">Verify Your Identity</h1>
<p class="text-center text-gray-600 dark:text-gray-300 mb-6">
@switch (Model.FactorType)
{
case AccountAuthFactorType.EmailCode:
<span>We've sent a verification code to your email.</span>
break;
case AccountAuthFactorType.InAppCode:
<span>Enter the code from your authenticator app.</span>
break;
case AccountAuthFactorType.TimedCode:
<span>Enter your time-based verification code.</span>
break;
case AccountAuthFactorType.PinCode:
<span>Enter your PIN code.</span>
break;
case AccountAuthFactorType.Password:
<span>Enter your password.</span>
break;
default:
<span>Please verify your identity.</span>
break;
}
</p>
<div class="hero min-h-full bg-base-200">
<div class="hero-content w-full max-w-md">
<div class="card w-full bg-base-100 shadow-xl">
<div class="card-body px-8 py-7">
<h1 class="card-title justify-center text-2xl font-bold">Verify Your Identity</h1>
<p class="text-center">
@switch (Model.FactorType)
{
case AccountAuthFactorType.EmailCode:
<span>We've sent a verification code to your email.</span>
break;
case AccountAuthFactorType.InAppCode:
<span>Enter the code from your authenticator app.</span>
break;
case AccountAuthFactorType.TimedCode:
<span>Enter your time-based verification code.</span>
break;
case AccountAuthFactorType.PinCode:
<span>Enter your PIN code.</span>
break;
case AccountAuthFactorType.Password:
<span>Enter your password.</span>
break;
default:
<span>Please verify your identity.</span>
break;
}
</p>
@if (Model.AuthChallenge == null)
{
<p class="text-red-500 text-center">Challenge not found or expired.</p>
}
else if (Model.AuthChallenge.StepRemain == 0)
{
<p class="text-green-600 dark:text-green-400 text-center">Verification successful. Redirecting...</p>
}
else
{
<form method="post" class="space-y-4">
<div asp-validation-summary="ModelOnly" class="text-red-500 text-sm"></div>
<div class="mb-4">
<label asp-for="Code" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
@(Model.FactorType == AccountAuthFactorType.Password ? "Use your password" : "Verification Code")
</label>
<input asp-for="Code"
class="form-input mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-500 focus:ring-opacity-50 dark:bg-gray-700 dark:border-gray-600 dark:text-white px-4 py-2"
autocomplete="one-time-code"
type="password"
autofocus />
<span asp-validation-for="Code" class="text-red-500 text-sm mt-1"></span>
</div>
@if (Model.AuthChallenge == null)
{
<div class="alert alert-error">
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
<span>Challenge not found or expired.</span>
</div>
}
else if (Model.AuthChallenge.StepRemain == 0)
{
<div class="alert alert-success">
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
<span>Verification successful. Redirecting...</span>
</div>
}
else
{
<form method="post" class="space-y-4">
<div asp-validation-summary="ModelOnly" class="text-error text-sm"></div>
<div class="form-control">
<label asp-for="Code" class="label">
<span class="label-text">@(Model.FactorType == AccountAuthFactorType.Password ? "Use your password" : "Verification Code")</span>
</label>
<input asp-for="Code"
class="input input-bordered w-full"
autocomplete="one-time-code"
type="password"
autofocus />
<span asp-validation-for="Code" class="text-error text-sm mt-1"></span>
</div>
<button type="submit"
class="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">
Verify
</button>
<div class="form-control mt-6">
<button type="submit" class="btn btn-primary w-full">Verify</button>
</div>
<div class="text-center mt-4">
<a asp-page="SelectFactor" asp-route-id="@Model.Id" class="text-sm text-blue-600 hover:text-blue-500 dark:text-blue-400 dark:hover:text-blue-300">
← Back to authentication methods
</a>
</div>
</form>
}
<div class="text-center mt-4">
<a asp-page="SelectFactor" asp-route-id="@Model.Id" class="link link-primary text-sm">
← Back to authentication methods
</a>
</div>
</form>
}
</div>
</div>
</div>
</div>
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
}