enh: exp token check

This commit is contained in:
Timothy Jaeryang Baek
2025-04-24 03:12:22 +09:00
parent 91e758f3ec
commit 28ec3069de
3 changed files with 103 additions and 85 deletions

View File

@@ -251,77 +251,79 @@
</div>
{/if}
<div class="app relative">
<div
class=" text-gray-700 dark:text-gray-100 bg-white dark:bg-gray-900 h-screen max-h-[100dvh] overflow-auto flex flex-row justify-end"
>
{#if !['user', 'admin'].includes($user?.role)}
<AccountPending />
{:else if localDBChats.length > 0}
<div class="fixed w-full h-full flex z-50">
<div
class="absolute w-full h-full backdrop-blur-md bg-white/20 dark:bg-gray-900/50 flex justify-center"
>
<div class="m-auto pb-44 flex flex-col justify-center">
<div class="max-w-md">
<div class="text-center dark:text-white text-2xl font-medium z-50">
Important Update<br /> Action Required for Chat Log Storage
</div>
{#if $user}
<div class="app relative">
<div
class=" text-gray-700 dark:text-gray-100 bg-white dark:bg-gray-900 h-screen max-h-[100dvh] overflow-auto flex flex-row justify-end"
>
{#if !['user', 'admin'].includes($user?.role)}
<AccountPending />
{:else if localDBChats.length > 0}
<div class="fixed w-full h-full flex z-50">
<div
class="absolute w-full h-full backdrop-blur-md bg-white/20 dark:bg-gray-900/50 flex justify-center"
>
<div class="m-auto pb-44 flex flex-col justify-center">
<div class="max-w-md">
<div class="text-center dark:text-white text-2xl font-medium z-50">
Important Update<br /> Action Required for Chat Log Storage
</div>
<div class=" mt-4 text-center text-sm dark:text-gray-200 w-full">
{$i18n.t(
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through"
)}
<span class="font-semibold dark:text-white"
>{$i18n.t('Settings')} > {$i18n.t('Chats')} > {$i18n.t('Import Chats')}</span
>. {$i18n.t(
'This ensures that your valuable conversations are securely saved to your backend database. Thank you!'
)}
</div>
<div class=" mt-4 text-center text-sm dark:text-gray-200 w-full">
{$i18n.t(
"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through"
)}
<span class="font-semibold dark:text-white"
>{$i18n.t('Settings')} > {$i18n.t('Chats')} > {$i18n.t('Import Chats')}</span
>. {$i18n.t(
'This ensures that your valuable conversations are securely saved to your backend database. Thank you!'
)}
</div>
<div class=" mt-6 mx-auto relative group w-fit">
<button
class="relative z-20 flex px-5 py-2 rounded-full bg-white border border-gray-100 dark:border-none hover:bg-gray-100 transition font-medium text-sm"
on:click={async () => {
let blob = new Blob([JSON.stringify(localDBChats)], {
type: 'application/json'
});
saveAs(blob, `chat-export-${Date.now()}.json`);
<div class=" mt-6 mx-auto relative group w-fit">
<button
class="relative z-20 flex px-5 py-2 rounded-full bg-white border border-gray-100 dark:border-none hover:bg-gray-100 transition font-medium text-sm"
on:click={async () => {
let blob = new Blob([JSON.stringify(localDBChats)], {
type: 'application/json'
});
saveAs(blob, `chat-export-${Date.now()}.json`);
const tx = DB.transaction('chats', 'readwrite');
await Promise.all([tx.store.clear(), tx.done]);
await deleteDB('Chats');
const tx = DB.transaction('chats', 'readwrite');
await Promise.all([tx.store.clear(), tx.done]);
await deleteDB('Chats');
localDBChats = [];
}}
>
Download & Delete
</button>
localDBChats = [];
}}
>
Download & Delete
</button>
<button
class="text-xs text-center w-full mt-2 text-gray-400 underline"
on:click={async () => {
localDBChats = [];
}}>{$i18n.t('Close')}</button
>
<button
class="text-xs text-center w-full mt-2 text-gray-400 underline"
on:click={async () => {
localDBChats = [];
}}>{$i18n.t('Close')}</button
>
</div>
</div>
</div>
</div>
</div>
</div>
{/if}
{/if}
<Sidebar />
<Sidebar />
{#if loaded}
<slot />
{:else}
<div class="w-full flex-1 h-full flex items-center justify-center">
<Spinner />
</div>
{/if}
{#if loaded}
<slot />
{:else}
<div class="w-full flex-1 h-full flex items-center justify-center">
<Spinner />
</div>
{/if}
</div>
</div>
</div>
{/if}
<style>
.loading {

View File

@@ -54,6 +54,7 @@
const bc = new BroadcastChannel('active-tab-channel');
let loaded = false;
let tokenTimer = null;
const BREAKPOINT = 768;
@@ -443,6 +444,24 @@
}
};
const checkTokenExpiry = () => {
const exp = $user?.expires_at; // token expiry time in unix timestamp
const now = Math.floor(Date.now() / 1000); // current time in unix timestamp
if (!exp) {
// If no expiry time is set, do nothing
return;
}
if (now >= exp) {
localStorage.removeItem('token');
// redirect to auth page
if ($page.url.pathname !== '/auth') {
goto(`/auth`);
}
}
};
onMount(async () => {
if (typeof window !== 'undefined' && window.applyTheme) {
window.applyTheme();
@@ -560,6 +579,12 @@
await user.set(sessionUser);
await config.set(await getBackendConfig());
// Set up the token expiry check
if (tokenTimer) {
clearInterval(tokenTimer);
}
tokenTimer = setInterval(checkTokenExpiry, 1000);
} else {
// Redirect Invalid Session User to /auth Page
localStorage.removeItem('token');