fix(auth): complete logout state cleanup and admin protected route token validation [TASK-26.8] [TASK-26.9]

This commit is contained in:
parsa aghaei 2026-08-05 14:39:31 +03:30
parent 350182c5a4
commit 7f3c04acf5
3 changed files with 39 additions and 5 deletions

View File

@ -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 در سفارش.

View File

@ -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 <Navigate to="/login" replace />;
}
if (isValidating) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50">
<div className="w-8 h-8 border-4 border-purple-600 border-t-transparent rounded-full animate-spin"></div>
</div>
);
}
return <Outlet />;
}

View File

@ -164,7 +164,9 @@ export const useUserStore = create<UserStore>()(
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,