From 7f3c04acf57aebd38e94e2d32e9c61d986d14d8b Mon Sep 17 00:00:00 2001
From: parsa aghaei
Date: Wed, 5 Aug 2026 14:39:31 +0330
Subject: [PATCH] fix(auth): complete logout state cleanup and admin protected
route token validation [TASK-26.8] [TASK-26.9]
---
docs/backlog.md | 4 +-
.../src/components/ProtectedRoute.tsx | 38 +++++++++++++++++--
frontend/application/lib/store/userStore.ts | 2 +
3 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/docs/backlog.md b/docs/backlog.md
index 61fa59f..00ca1e6 100644
--- a/docs/backlog.md
+++ b/docs/backlog.md
@@ -205,8 +205,8 @@
- [x] **TASK-26.5 [Remove OTP Console Log]:** حذف لاگ شدن کد OTP در کنسول سرور جهت جلوگیری از افشای امنیتی.
- [ ] **TASK-26.6 [JWT Refresh Token Implementation]:** پیادهسازی مکانیزم کامل Refresh Token برای تمدید خودکار نشست کاربر.
- [ ] **TASK-26.7 [SSR & HttpOnly Cookie Auth]:** ذخیره توکنها درون HttpOnly Cookie جهت همگامسازی کامل Server & Client Components در Next.js.
-- [ ] **TASK-26.8 [Logout State Cleanup]:** پاکسازی کامل کاتالوگ، سبد خرید و تمام کشهای کاربر هنگام خروج (Logout Cleanup).
-- [ ] **TASK-26.9 [Admin Token Validation Guard]:** اعتبارسنجی واقعی توکن ادمین در `ProtectedRoute.tsx` از طریق فراخوانی API پروفایل در هنگام لود پنل.
+- [x] **TASK-26.8 [Logout State Cleanup]:** پاکسازی کامل کاتالوگ، سبد خرید و تمام کشهای کاربر هنگام خروج (Logout Cleanup).
+- [x] **TASK-26.9 [Admin Token Validation Guard]:** اعتبارسنجی واقعی توکن ادمین در `ProtectedRoute.tsx` از طریق فراخوانی API پروفایل در هنگام لود پنل.
- [ ] **TASK-26.10 [Fix Pagination & Search Query Overwrite]:** اصلاح منطق `whereClause` در `products.service.ts` جهت جلوگیری از اوررایت شدن فیلترها.
- [ ] **TASK-26.11 [Price Range & Sorting Filters]:** افزودن فیلتر محدوده قیمت (`minPrice`, `maxPrice`) و مرتبسازی (`sort`) به DTO و اندپویینتهای محصولات.
- [ ] **TASK-26.12 [Sync Fallback IDs with Database]:** همگامسازی شناسه محصولات استاتیک فرانتاند با دیتابیس واقعی جهت جلوگیری از 404 در سفارش.
diff --git a/frontend/admin-panel/src/components/ProtectedRoute.tsx b/frontend/admin-panel/src/components/ProtectedRoute.tsx
index 2fc85db..1bc4dc4 100644
--- a/frontend/admin-panel/src/components/ProtectedRoute.tsx
+++ b/frontend/admin-panel/src/components/ProtectedRoute.tsx
@@ -1,11 +1,43 @@
+import { useState, useEffect } from 'react';
import { Navigate, Outlet } from 'react-router-dom';
+import api from '../services/api';
export default function ProtectedRoute() {
const token = localStorage.getItem('adminToken');
-
- if (!token) {
+ const [isValidating, setIsValidating] = useState(true);
+ const [isValid, setIsValid] = useState(true);
+
+ useEffect(() => {
+ if (!token) {
+ setIsValid(false);
+ setIsValidating(false);
+ return;
+ }
+
+ api.get('/users/profile')
+ .then(() => {
+ setIsValid(true);
+ })
+ .catch(() => {
+ localStorage.removeItem('adminToken');
+ setIsValid(false);
+ })
+ .finally(() => {
+ setIsValidating(false);
+ });
+ }, [token]);
+
+ if (!token || !isValid) {
return ;
}
-
+
+ if (isValidating) {
+ return (
+
+ );
+ }
+
return ;
}
diff --git a/frontend/application/lib/store/userStore.ts b/frontend/application/lib/store/userStore.ts
index 8149338..7cb780f 100644
--- a/frontend/application/lib/store/userStore.ts
+++ b/frontend/application/lib/store/userStore.ts
@@ -164,7 +164,9 @@ export const useUserStore = create()(
logout: () => {
authService.logout();
try { usePetStore.getState().reset(); } catch {}
+ try { useCartStore.getState().clearCart(); } catch {}
try { localStorage.removeItem("canina-pets"); } catch {}
+ try { localStorage.removeItem("canina-cart-storage"); } catch {}
set({
role: "User_Guest",
isLoggedIn: false,