fix: 배포 후 관리자 세션 복구 처리
This commit is contained in:
@@ -13,8 +13,16 @@
|
|||||||
<component type="typeof(HeadOutlet)" render-mode="InteractiveServer" />
|
<component type="typeof(HeadOutlet)" render-mode="InteractiveServer" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<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)" />
|
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
|
||||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||||
|
<script src="/taxbaik/js/admin-session.js"></script>
|
||||||
<script src="_framework/blazor.web.js"></script>
|
<script src="_framework/blazor.web.js"></script>
|
||||||
|
<script>window.taxbaikAdminSession?.watchReconnect();</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
|
|
||||||
await ApiClient.SetAuthToken(response.Token);
|
await ApiClient.SetAuthToken(response.Token);
|
||||||
await AuthStateProvider.LoginAsync(response.Token);
|
await AuthStateProvider.LoginAsync(response.Token);
|
||||||
NavigationManager.NavigateTo("/taxbaik/admin/dashboard", forceLoad: false);
|
NavigationManager.NavigateTo(GetReturnUrl(), forceLoad: false);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -100,4 +100,22 @@
|
|||||||
public string Username { get; set; } = "";
|
public string Username { get; set; } = "";
|
||||||
public string Password { 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 NavigationManager Navigation
|
||||||
|
@inject IJSRuntime Js
|
||||||
|
|
||||||
@code {
|
@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));
|
var returnUrl = Uri.EscapeDataString(Navigation.ToBaseRelativePath(Navigation.Uri));
|
||||||
Navigation.NavigateTo($"/taxbaik/admin/login?returnUrl={returnUrl}", replace: true);
|
Navigation.NavigateTo($"/taxbaik/admin/login?returnUrl={returnUrl}", replace: true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||||
@using Microsoft.AspNetCore.Components.Authorization
|
@using Microsoft.AspNetCore.Components.Authorization
|
||||||
@using Microsoft.AspNetCore.Authorization
|
@using Microsoft.AspNetCore.Authorization
|
||||||
|
@using Microsoft.JSInterop
|
||||||
@using MudBlazor
|
@using MudBlazor
|
||||||
@using TaxBaik.Web.Services
|
@using TaxBaik.Web.Services
|
||||||
@using TaxBaik.Domain.Entities
|
@using TaxBaik.Domain.Entities
|
||||||
|
|||||||
@@ -169,6 +169,41 @@ button:disabled {
|
|||||||
opacity: 0.6;
|
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 */
|
/* Responsive */
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.mud-container-maxwidth-small {
|
.mud-container-maxwidth-small {
|
||||||
|
|||||||
@@ -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'] });
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user