fix: 배포 후 관리자 세션 복구 처리
TaxBaik CI/CD / build-and-deploy (push) Successful in 56s
TaxBaik Browser E2E / browser-e2e (push) Failing after 3m3s

This commit is contained in:
2026-06-27 21:38:11 +09:00
parent 661ffbbf2c
commit d58e524dfc
6 changed files with 95 additions and 2 deletions
+8
View File
@@ -13,8 +13,16 @@
<component type="typeof(HeadOutlet)" render-mode="InteractiveServer" />
</head>
<body>
<div id="components-reconnect-modal" class="admin-reconnect-modal">
<div class="admin-reconnect-card">
<strong>관리자 세션을 다시 연결하고 있습니다.</strong>
<span>배포 또는 서버 재시작 중이면 잠시 후 자동으로 새로고침됩니다.</span>
</div>
</div>
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
<script src="/taxbaik/js/admin-session.js"></script>
<script src="_framework/blazor.web.js"></script>
<script>window.taxbaikAdminSession?.watchReconnect();</script>
</body>
</html>
+19 -1
View File
@@ -80,7 +80,7 @@
await ApiClient.SetAuthToken(response.Token);
await AuthStateProvider.LoginAsync(response.Token);
NavigationManager.NavigateTo("/taxbaik/admin/dashboard", forceLoad: false);
NavigationManager.NavigateTo(GetReturnUrl(), forceLoad: false);
}
catch
{
@@ -100,4 +100,22 @@
public string Username { get; set; } = "";
public string Password { get; set; } = "";
}
private string GetReturnUrl()
{
var uri = NavigationManager.ToAbsoluteUri(NavigationManager.Uri);
if (!Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query).TryGetValue("returnUrl", out var returnUrl)
|| string.IsNullOrWhiteSpace(returnUrl))
{
return "/taxbaik/admin/dashboard";
}
var value = returnUrl.ToString();
if (!value.StartsWith("admin", StringComparison.OrdinalIgnoreCase))
{
return "/taxbaik/admin/dashboard";
}
return $"/taxbaik/{value.TrimStart('/')}";
}
}
@@ -1,8 +1,13 @@
@inject NavigationManager Navigation
@inject IJSRuntime Js
@code {
protected override void OnInitialized()
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
return;
await Js.InvokeVoidAsync("taxbaikAdminSession.clearAuthToken");
var returnUrl = Uri.EscapeDataString(Navigation.ToBaseRelativePath(Navigation.Uri));
Navigation.NavigateTo($"/taxbaik/admin/login?returnUrl={returnUrl}", replace: true);
}
@@ -6,6 +6,7 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Authorization
@using Microsoft.JSInterop
@using MudBlazor
@using TaxBaik.Web.Services
@using TaxBaik.Domain.Entities
+35
View File
@@ -169,6 +169,41 @@ button:disabled {
opacity: 0.6;
}
.admin-reconnect-modal {
display: none;
}
.admin-reconnect-modal.components-reconnect-show,
.admin-reconnect-modal.components-reconnect-failed,
.admin-reconnect-modal.components-reconnect-rejected {
position: fixed;
inset: 0;
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
background: rgba(15, 23, 42, 0.48);
}
.admin-reconnect-card {
width: min(420px, 100%);
padding: 24px;
border-radius: 16px;
background: #fff;
box-shadow: 0 24px 80px rgba(15, 23, 42, 0.28);
}
.admin-reconnect-card strong,
.admin-reconnect-card span {
display: block;
}
.admin-reconnect-card span {
margin-top: 8px;
color: #64748b;
}
/* Responsive */
@media (max-width: 600px) {
.mud-container-maxwidth-small {
+26
View File
@@ -0,0 +1,26 @@
window.taxbaikAdminSession = {
clearAuthToken: function () {
try {
localStorage.removeItem('auth_token');
} catch {
// Ignore storage errors; redirect still recovers the session.
}
},
watchReconnect: function () {
const modal = document.getElementById('components-reconnect-modal');
if (!modal) {
return;
}
const reloadOnRejectedCircuit = () => {
const className = modal.className || '';
if (className.includes('components-reconnect-failed') ||
className.includes('components-reconnect-rejected')) {
window.setTimeout(() => window.location.reload(), 1500);
}
};
new MutationObserver(reloadOnRejectedCircuit)
.observe(modal, { attributes: true, attributeFilter: ['class'] });
}
};